Example #1
0
        public ValueTask <LogoutModel> LogoutCallback(IdentityHttpRequest request)
        {
            var callbackBinding = Saml2Binding.GetBindingForRequest(request, BindingDirection.Response);

            callbackBinding.ValidateSignature(identityProviderCert, true);
            callbackBinding.ValidateFields(new string[] { redirectUrl });

            var callbackDocument = new Saml2LogoutResponse(callbackBinding);

            SamlIDManager.Validate(serviceProvider, callbackDocument.InResponseTo);

            if (String.IsNullOrWhiteSpace(callbackDocument.Issuer))
            {
                return(new ValueTask <LogoutModel>((LogoutModel)null));
            }

            var logout = new LogoutModel()
            {
                ServiceProvider = callbackDocument.Issuer,
                State           = null,
                OtherClaims     = null
            };

            return(new ValueTask <LogoutModel>(logout));
        }
Example #2
0
        internal Saml2FormBinding(IdentityHttpRequest request, BindingDirection bindingDirection)
        {
            this.BindingDirection = bindingDirection;
            string samlEncoded = this.BindingDirection switch
            {
                BindingDirection.Request => request.Form[Saml2Names.RequestParameterName],
                BindingDirection.Response => request.Form[Saml2Names.ResponseParameterName],
                _ => throw new NotImplementedException(),
            };
            var samlRequestDecoded = DecodeSaml(samlEncoded);

            this.Document = new XmlDocument();
            this.Document.LoadXml(samlRequestDecoded);

            this.HasSignature = X509XmlSigner.HasSignature(this.Document.DocumentElement);
            if (this.HasSignature)
            {
                this.SignatureAlgorithm = X509XmlSigner.GetSignatureAlgorithm(this.Document.DocumentElement);
                this.DigestAlgorithm    = X509XmlSigner.GetDigestAlgorithm(this.Document.DocumentElement);
            }

            this.HasEncryption = X509XmlEncryptor.HasEncryptedDataElements(this.Document.DocumentElement);
            if (this.HasEncryption)
            {
                this.EncryptionAlgorithm = X509XmlEncryptor.GetEncryptionAlgorithm(this.Document.DocumentElement);
            }
        }
Example #3
0
        internal Saml2QueryBinding(IdentityHttpRequest request, BindingDirection bindingDirection)
        {
            this.BindingDirection = bindingDirection;
            string samlEncoded = this.BindingDirection switch
            {
                BindingDirection.Request => request.Query[Saml2Names.RequestParameterName],
                BindingDirection.Response => request.Query[Saml2Names.ResponseParameterName],
                _ => throw new NotImplementedException(),
            };

            //var relayState = (string)request.Query[Saml2Names.RelayStateParameterName];
            var sigAlg = (string)request.Query[Saml2Names.SignatureAlgorithmParameterName];

            this.Signature = request.Query[Saml2Names.SignatureParameterName];

            this.singingInput = request.QueryString.Substring(1, request.QueryString.IndexOf("&" + Saml2Names.SignatureParameterName + "=") - 1);

            if (samlEncoded == null)
            {
                return;
            }

            var samlRequestDecoded = DecodeSaml(samlEncoded);

            this.Document = new XmlDocument();
            this.Document.LoadXml(samlRequestDecoded);

            this.SignatureAlgorithm = Algorithms.GetSignatureAlgorithmFromUrl(sigAlg);
        }
Example #4
0
        internal OpenIDQueryBinding(IdentityHttpRequest request, BindingDirection bindingDirection)
        {
            this.BindingDirection = bindingDirection;

            this.Document = new JObject();
            foreach (var queryItem in request.Query)
            {
                this.Document.Add(queryItem.Key, JToken.FromObject((string)queryItem.Value));
            }
        }
Example #5
0
        internal OAuth2FormBinding(IdentityHttpRequest request, BindingDirection bindingDirection)
        {
            this.BindingDirection = bindingDirection;

            this.Document = new JObject();
            foreach (var formItem in request.Form)
            {
                this.Document.Add(formItem.Key, JToken.FromObject((string)formItem.Value));
            }
        }
Example #6
0
 public static OAuth2Binding GetBindingForRequest(IdentityHttpRequest request, BindingDirection flowDirection)
 {
     if (request.HasFormContentType)
     {
         return(new OAuth2FormBinding(request, flowDirection));
     }
     else
     {
         return(new OAuth2QueryBinding(request, flowDirection));
     }
 }
Example #7
0
 public static bool IsOAuth2Binding(IdentityHttpRequest request)
 {
     if (request.HasFormContentType)
     {
         return(request.Form.Keys.Contains(OAuth2Binding.ClientFormName));
     }
     else
     {
         return(request.Query.Keys.Contains(OAuth2Binding.ClientFormName));
     }
 }
Example #8
0
 public static Saml2Binding GetBindingForRequest(IdentityHttpRequest request, BindingDirection bindingDirection)
 {
     if (request.HasFormContentType)
     {
         return(new Saml2FormBinding(request, bindingDirection));
     }
     else
     {
         return(new Saml2QueryBinding(request, bindingDirection));
     }
 }
Example #9
0
 public static bool IsSaml2Binding(IdentityHttpRequest request)
 {
     if (request.HasFormContentType)
     {
         return(request.Form.Keys.Contains(Saml2Names.RequestParameterName) || request.Form.Keys.Contains(Saml2Names.ResponseParameterName));
     }
     else
     {
         return(request.Query.Keys.Contains(Saml2Names.RequestParameterName) || request.Query.Keys.Contains(Saml2Names.ResponseParameterName));
     }
 }
Example #10
0
 public static bool IsCodeBinding(IdentityHttpRequest request)
 {
     if (request.HasFormContentType)
     {
         return(request.Form.Keys.Contains("code"));
     }
     else
     {
         return(request.Query.Keys.Contains("code"));
     }
 }
Example #11
0
        public ValueTask <LogoutModel> LogoutCallback(IdentityHttpRequest request)
        {
            var callbackBinding = OpenIDBinding.GetBindingForRequest(request, BindingDirection.Response);

            var callbackDocument = new OpenIDLogoutResponse(callbackBinding);

            var logout = new LogoutModel()
            {
                ServiceProvider = serviceProvider,
                State           = callbackDocument.State,
                OtherClaims     = callbackDocument.OtherClaims
            };

            return(new ValueTask <LogoutModel>(logout));
        }
Example #12
0
        internal OpenIDJwtQueryBinding(IdentityHttpRequest request, BindingDirection bindingDirection)
        {
            this.BindingDirection = bindingDirection;

            string token;

            if (request.Query.ContainsKey(OpenIDJwtBinding.IdTokenFormName))
            {
                token       = request.Query[OpenIDJwtBinding.IdTokenFormName];
                accessToken = token;
            }
            else if (request.Query.ContainsKey(OpenIDJwtBinding.AccessTokenFormName))
            {
                token       = request.Query[OpenIDJwtBinding.AccessTokenFormName];
                accessToken = token;
            }
            else
            {
                throw new IdentityProviderException("Missing JWT Token");
            }

            var parts            = token.Split(OpenIDJwtQueryBinding.tokenDelimiter);
            var jwtHeaderString  = DecodeJwt(parts[0]);
            var jwtPayloadString = DecodeJwt(parts[1]);

            if (!String.IsNullOrWhiteSpace(parts[2]))
            {
                this.Signature = parts[2];
            }

            this.singingInput = parts[0] + OpenIDJwtQueryBinding.tokenDelimiter + parts[1];

            var jwtHeader = JsonConvert.DeserializeObject <JwtHeader>(jwtHeaderString);

            DeserializeJwtPayload(jwtPayloadString);

            foreach (var queryValue in request.Query)
            {
                this.Document.Add(queryValue.Key, (string)queryValue.Value);
            }

            if (!this.Document.ContainsKey(nameof(JwtHeader.X509Thumbprint)) && jwtHeader.X509Thumbprint != null)
            {
                this.Document.Add(nameof(JwtHeader.X509Thumbprint), JToken.FromObject(jwtHeader.X509Thumbprint));
            }

            this.SignatureAlgorithm = Algorithms.GetSignatureAlgorithmFromJwt(jwtHeader.Algorithm);
        }
Example #13
0
        public ValueTask <IdentityModel> LoginCallback(IdentityHttpRequest request)
        {
            var callbackBinding = Saml2Binding.GetBindingForRequest(request, BindingDirection.Response);

            callbackBinding.ValidateSignature(identityProviderCert, true);
            callbackBinding.Decrypt(serviceProviderCert, requiredEncryption);
            callbackBinding.ValidateFields(new string[] { redirectUrl });

            var callbackDocument = new Saml2AuthnResponse(callbackBinding);

            SamlIDManager.Validate(serviceProvider, callbackDocument.InResponseTo);

            if (callbackDocument.Audience != serviceProvider)
            {
                throw new IdentityProviderException("Saml Audience is not valid",
                                                    String.Format("Received: {0}, Expected: {1}", serviceProvider, callbackDocument.Audience));
            }

            if (String.IsNullOrWhiteSpace(callbackDocument.UserID))
            {
                return(new ValueTask <IdentityModel>((IdentityModel)null));
            }

            var identity = new IdentityModel()
            {
                UserID          = callbackDocument.UserID,
                UserName        = callbackDocument.UserName,
                Name            = callbackDocument.UserName,
                Roles           = callbackDocument.Roles,
                ServiceProvider = callbackDocument.Issuer,
                State           = null,
                OtherClaims     = null
            };

            return(new ValueTask <IdentityModel>(identity));
        }
Example #14
0
        public async ValueTask <IdentityModel> LoginCallback(IdentityHttpRequest request)
        {
            OpenIDJwtBinding callbackBinding;

            if (OpenIDJwtBinding.IsCodeBinding(request))
            {
                var callbackCodeBinding = OpenIDBinding.GetBindingForRequest(request, BindingDirection.Response);

                var callbackCodeDocument = new OpenIDLoginResponse(callbackCodeBinding);
                if (!String.IsNullOrWhiteSpace(callbackCodeDocument.Error))
                {
                    throw new IdentityProviderException($"{callbackCodeDocument.Error}: {callbackCodeDocument.ErrorDescription}");
                }

                //Get Token--------------------
                var requestTokenDocument = new OpenIDTokenRequest(callbackCodeDocument.AccessCode, this.secret, OpenIDGrantType.authorization_code, redirectUrl);
                var requestTokenBinding  = OpenIDBinding.GetBindingForDocument(requestTokenDocument, BindingType.Form);

                var requestTokenBody = requestTokenBinding.GetContent();
                var requestToken     = WebRequest.Create(tokenUrl);
                requestToken.Method      = "POST";
                requestToken.ContentType = "application/x-www-form-urlencoded";
                var requestTokenBodyBytes = Encoding.UTF8.GetBytes(requestTokenBody);
                requestToken.ContentLength = requestTokenBodyBytes.Length;
                using (var stream = await requestToken.GetRequestStreamAsync())
                {
#if NETSTANDARD2_0 || NET461_OR_GREATER
                    await stream.WriteAsync(requestTokenBodyBytes, 0, requestTokenBodyBytes.Length);
#else
                    await stream.WriteAsync(requestTokenBodyBytes.AsMemory());
#endif
                    await stream.FlushAsync();
                }

                WebResponse responseToken;
                try
                {
                    responseToken = await requestToken.GetResponseAsync();
                }
                catch (WebException ex)
                {
                    if (ex.Response == null)
                    {
                        throw ex;
                    }
                    var responseTokenStream = ex.Response.GetResponseStream();
                    var error = await new StreamReader(responseTokenStream).ReadToEndAsync();
                    ex.Response.Close();
                    ex.Response.Dispose();
                    throw new IdentityProviderException(error);
                }

                //access_code is a JWT
                callbackBinding = OpenIDJwtBinding.GetBindingForResponse(responseToken, BindingDirection.Response);
            }
            else
            {
                callbackBinding = OpenIDJwtBinding.GetBindingForRequest(request, BindingDirection.Response);
            }

            var callbackDocument = new OpenIDLoginResponse(callbackBinding);
            if (!String.IsNullOrWhiteSpace(callbackDocument.Error))
            {
                throw new IdentityProviderException($"{callbackDocument.Error}: {callbackDocument.ErrorDescription}");
            }

            NonceManager.Validate(serviceProvider, callbackDocument.Nonce);

            if (callbackDocument.Audience != serviceProvider)
            {
                throw new IdentityProviderException("OpenID Audience is not valid", $"Received: {serviceProvider}, Expected: {callbackDocument.Audience}");
            }

            var keys = await GetSignaturePublicKeys(this.identityProviderCertUrl);

            var key = keys.FirstOrDefault(x => x.X509Thumbprint == callbackDocument.X509Thumbprint);
            if (key == null)
            {
                key = keys.FirstOrDefault(x => x.KeyID == callbackDocument.KeyID);
            }
            if (key == null)
            {
                throw new IdentityProviderException("Identity Provider OpenID certificate not found from Json Key Url");
            }
            if (key.KeyType != "RSA")
            {
                throw new IdentityProviderException("Identity Provider OpenID only supporting RSA at the moment");
            }

            RSA rsa;
            if (key.X509Certificates == null || key.X509Certificates.Length == 0)
            {
                var rsaParams = new RSAParameters()
                {
                    Modulus  = Base64UrlEncoder.FromBase64String(key.Modulus),
                    Exponent = Base64UrlEncoder.FromBase64String(key.Exponent)
                };
                rsa = RSA.Create();
                rsa.ImportParameters(rsaParams);
            }
            else
            {
                var certString = key.X509Certificates.First();
                var certBytes  = Convert.FromBase64String(certString);
                var cert       = new X509Certificate2(certBytes);
                rsa = cert.GetRSAPublicKey();
            }

            callbackBinding.ValidateSignature(rsa, requiredSignature);
            callbackBinding.ValidateFields();

            var identity = new IdentityModel()
            {
                UserID          = callbackDocument.UserID,
                UserName        = callbackDocument.UserName ?? callbackDocument.Emails?.FirstOrDefault(),
                Name            = callbackDocument.Name,
                Roles           = callbackDocument.Roles,
                ServiceProvider = callbackDocument.Issuer,
                OtherClaims     = callbackDocument.OtherClaims,
                State           = callbackDocument.State,
                AccessToken     = callbackBinding.AccessToken,
            };

            return(identity);
        }
Example #15
0
        public async ValueTask <IdentityModel> LoginCallback(IdentityHttpRequest request)
        {
            var callbackBinding = OAuth2Binding.GetBindingForRequest(request, BindingDirection.Response);

            var callbackDocument = new OAuth2LoginResponse(callbackBinding);

            var callbackServiceProvider = callbackDocument.ServiceProvider;
            var code = callbackDocument.AccessCode;

            if (code == null)
            {
                return(null);
            }

            if (serviceProvider != callbackServiceProvider)
            {
                throw new IdentityProviderException("Service Providers do not match", $"Received: {serviceProvider}, Expected: {callbackServiceProvider}");
            }

            //Get Token--------------------
            var requestTokenDocument = new OAuth2TokenRequest(serviceProvider, code);
            var requestTokenBinding  = OAuth2Binding.GetBindingForDocument(requestTokenDocument, BindingType.Query);

            var requestTokenAction = requestTokenBinding.GetResponse(tokenUrl);
            var requestToken       = WebRequest.Create(requestTokenAction.RedirectUrl);
            var responseToken      = await requestToken.GetResponseAsync();

            var responseTokenBinding  = OAuth2Binding.GetBindingForResponse(responseToken, BindingDirection.Response);
            var responseTokenDocument = new OAuth2TokenResponse(responseTokenBinding);

            //Get Identity---------------
            var requestIdentityDocument = new OAuth2IdentityRequest(serviceProvider, responseTokenDocument.Token);
            var requestIdentityBinding  = OAuth2Binding.GetBindingForDocument(requestIdentityDocument, BindingType.Query);

            var requestIdentityAction = requestIdentityBinding.GetResponse(identityUrl);
            var requestIdentity       = WebRequest.Create(requestIdentityAction.RedirectUrl);
            var responseIdentity      = await requestIdentity.GetResponseAsync();

            var responseIdentityBinding  = OAuth2Binding.GetBindingForResponse(responseIdentity, BindingDirection.Response);
            var responseIdentityDocument = new OAuth2IdentityResponse(responseIdentityBinding);

            if (responseIdentityDocument.ServiceProvider != serviceProvider)
            {
                return(null);
            }

            if (String.IsNullOrWhiteSpace(responseIdentityDocument.UserID))
            {
                return(null);
            }

            var identity = new IdentityModel()
            {
                UserID          = responseIdentityDocument.UserID,
                UserName        = responseIdentityDocument.UserName,
                Name            = responseIdentityDocument.UserName,
                ServiceProvider = responseIdentityDocument.ServiceProvider,
                Roles           = responseIdentityDocument.Roles,
                OtherClaims     = null,
                State           = null,
                AccessToken     = responseTokenDocument.Token
            };

            return(identity);
        }