Exemple #1
0
        public void OpenIdConnectProtocolValidator_GenerateNonce()
        {
            List <string> errors = new List <string>();
            OpenIdConnectProtocolValidator protocolValidator = new OpenIdConnectProtocolValidator();
            string nonce          = protocolValidator.GenerateNonce();
            int    endOfTimestamp = nonce.IndexOf('.');

            if (endOfTimestamp == -1)
            {
                errors.Add("nonce does not have '.' seperator");
            }
            else
            {
            }
        }
        /// <summary>
        ///     Gets the authorization code request URL for the specified identity provider.
        /// </summary>
        /// <param name="idpLoginRequest">The oidc provider.</param>
        /// <param name="requestBaseUrl">The base url message.</param>
        /// <returns>Task&lt;Uri&gt;.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        public async Task <Uri> GetAuthorizationCodeRequestUrl(IdentityProviderLoginRequest idpLoginRequest, Uri requestBaseUrl)
        {
            if (idpLoginRequest == null)
            {
                throw new ArgumentNullException(nameof(idpLoginRequest));
            }

            if (requestBaseUrl == null)
            {
                throw new ArgumentNullException(nameof(requestBaseUrl));
            }

            if (string.IsNullOrWhiteSpace(idpLoginRequest.Tenant))
            {
                throw new ArgumentException(@"The tenant is invalid.", nameof(idpLoginRequest));
            }

            if (idpLoginRequest.IdentityProviderId <= 0)
            {
                throw new ArgumentException(@"The identity provider is invalid.", nameof(idpLoginRequest));
            }

            if (string.IsNullOrWhiteSpace(idpLoginRequest.RedirectUrl))
            {
                throw new ArgumentException(@"The redirect url is invalid.", nameof(idpLoginRequest));
            }

            long   tenantId;
            long   oidcProviderId;
            string oidcConfigurationUrl;
            string oidcClientId;
            bool   alwaysPrompt;

            using (new SecurityBypassContext())
                using (new TenantAdministratorContext(idpLoginRequest.Tenant))
                {
                    var oidcIdentityProvider = ReadiNow.Model.Entity.Get <OidcIdentityProvider>(idpLoginRequest.IdentityProviderId, GetOidcProviderFieldsToLoad());

                    if (oidcIdentityProvider == null)
                    {
                        throw new AuthenticationException("The identity provider does not exist.");
                    }

                    ValidateOidcProviderFields(oidcIdentityProvider);

                    // Store any required entity model fields upfront.
                    // Any code running after the await statement may run a different thread
                    tenantId             = RequestContext.TenantId;
                    oidcProviderId       = oidcIdentityProvider.Id;
                    oidcClientId         = oidcIdentityProvider.OidcClientId;
                    oidcConfigurationUrl = oidcIdentityProvider.OidcIdentityProviderConfigurationUrl;
                    alwaysPrompt         = oidcIdentityProvider.OidcAlwaysPrompt ?? true;
                }

            OpenIdConnectConfiguration oidcConfig;

            try
            {
                // Get the configuration
                oidcConfig = await _configurationManager.GetIdentityProviderConfigurationAsync(oidcConfigurationUrl);
            }
            catch (Exception ex)
            {
                throw new OidcProviderInvalidConfigurationException(ex);
            }

            var oidcProtocolValidator = new OpenIdConnectProtocolValidator();

            // Create authorization state
            var authStateObject = new OpenIdConnectAuthorizationState
            {
                Timestamp          = DateTime.UtcNow.Ticks,
                RedirectUrl        = idpLoginRequest.RedirectUrl,
                IdentityProviderId = oidcProviderId,
                TenantId           = tenantId,
                Nonce = oidcProtocolValidator.GenerateNonce()
            };

            // Serialize and encrypt state
            var stateJson      = JSON.Serialize(authStateObject);
            var cryptoProvider = new EncodingCryptoProvider();
            var encryptedState = cryptoProvider.EncryptAndEncode(stateJson);

            // Create code request oidc message
            var oidcMessage = new OpenIdConnectMessage
            {
                ClientId      = oidcClientId,
                IssuerAddress = oidcConfig.AuthorizationEndpoint,
                RedirectUri   = GetOidcAuthResponseUri(requestBaseUrl, idpLoginRequest.Tenant),
                Scope         = "openid email",
                ResponseType  = "code",
                State         = encryptedState,
                Nonce         = authStateObject.Nonce,
                Prompt        = alwaysPrompt ? "login" : null
            };

            // Get request url
            return(new Uri(oidcMessage.CreateAuthenticationRequestUrl()));
        }
Exemple #3
0
        public void OpenIdConnectProtocolValidator_Validate()
        {
            JwtSecurityToken jwt = new JwtSecurityToken();
            OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext();
            OpenIdConnectProtocolValidator         protocolValidator = new OpenIdConnectProtocolValidator();

            // jwt null
            Validate(jwt: null, protocolValidator: protocolValidator, validationContext: null, ee: ExpectedException.ArgumentNullException());

            // validationContext null
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: null, ee: ExpectedException.ArgumentNullException());

            // aud missing
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:"));

            // exp missing
            jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Aud, IdentityUtilities.DefaultAudience));
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:"));

            // iat missing
            jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Exp, EpochTime.GetIntDate(DateTime.UtcNow).ToString()));
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:"));

            // iss missing
            jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString()));
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:"));

            // add iis, nonce is not retuired.
            protocolValidator.RequireNonce = false;
            jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Iss, IdentityUtilities.DefaultIssuer));
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected);

            // nonce invalid
            string validNonce = protocolValidator.GenerateNonce();

            // add the valid 'nonce' but set validationContext.Nonce to a different 'nonce'.
            protocolValidator.RequireNonce = true;
            jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Nonce, validNonce));
            validationContext.Nonce = protocolValidator.GenerateNonce();
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10301:"));

            // sub missing, default not required
            validationContext.Nonce = validNonce;
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected);

            protocolValidator.RequireSub = true;
            Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:"));

            // authorizationCode invalid
            string validAuthorizationCode = protocolValidator.GenerateNonce();
            string validChash             = IdentityUtilities.CreateCHash(validAuthorizationCode, "SHA256");

            JwtSecurityToken jwtWithSignatureChash =
                new JwtSecurityToken
                (
                    audience: IdentityUtilities.DefaultAudience,
                    claims: new List <Claim>
            {
                new Claim(JwtRegisteredClaimNames.CHash, validChash),
                new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString()),
                new Claim(JwtRegisteredClaimNames.Nonce, validNonce),
                new Claim(JwtRegisteredClaimNames.Sub, "sub"),
            },
                    expires: DateTime.UtcNow + TimeSpan.FromHours(1),
                    issuer: IdentityUtilities.DefaultIssuer,
                    signingCredentials: IdentityUtilities.DefaultAsymmetricSigningCredentials
                );

            Dictionary <string, string> algmap = new Dictionary <string, string>(protocolValidator.HashAlgorithmMap);

            protocolValidator.HashAlgorithmMap.Clear();
            protocolValidator.HashAlgorithmMap.Add(JwtAlgorithms.RSA_SHA256, "SHA256");

            validationContext.Nonce             = validNonce;
            validationContext.AuthorizationCode = validNonce;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10304:"));

            // nonce and authorizationCode valid
            validationContext.AuthorizationCode = validAuthorizationCode;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected);

            // validate optional claims
            protocolValidator.RequireAcr = true;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10312:"));
            jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Acr, "acr"));

            protocolValidator.RequireAmr = true;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10313:"));
            jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Amr, "amr"));

            protocolValidator.RequireAuthTime = true;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10314:"));
            jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.AuthTime, "authTime"));

            protocolValidator.RequireAzp = true;
            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10315:"));
            jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Azp, "azp"));

            Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected);
        }