public void Validate(JwtSecurityToken jwt, OpenIdConnectProtocolValidator protocolValidator, OpenIdConnectProtocolValidationContext validationContext, ExpectedException ee) { try { protocolValidator.Validate(jwt, validationContext); ee.ProcessNoException(); } catch (Exception ex) { ee.ProcessException(ex); } }
public OpenIdConnectAuthenticationOptions(string authenticationType) : base(authenticationType) { AuthenticationMode = Security.AuthenticationMode.Active; BackchannelTimeout = TimeSpan.FromMinutes(1); Caption = OpenIdConnectAuthenticationDefaults.Caption; ProtocolValidator = new OpenIdConnectProtocolValidator(); RefreshOnIssuerKeyNotFound = true; ResponseType = OpenIdConnectResponseTypes.CodeIdToken; Scope = OpenIdConnectScopes.OpenIdProfile; TokenValidationParameters = new TokenValidationParameters(); UseTokenLifetime = true; }
public OpenIdConnectAuthenticationOptions(string authenticationScheme) { AuthenticationScheme = authenticationScheme; BackchannelTimeout = TimeSpan.FromMinutes(1); Caption = OpenIdConnectAuthenticationDefaults.Caption; GetClaimsFromUserInfoEndpoint = false; ProtocolValidator = new OpenIdConnectProtocolValidator(); RefreshOnIssuerKeyNotFound = true; ResponseMode = OpenIdConnectResponseModes.FormPost; ResponseType = OpenIdConnectResponseTypes.CodeIdToken; Scope = OpenIdConnectScopes.OpenIdProfile; TokenValidationParameters = new TokenValidationParameters(); UseTokenLifetime = true; }
public OpenIdConnectAuthenticationOptions(string authenticationScheme) { // REVIEW: why was this active by default?? //AuthenticationMode = AuthenticationMode.Active; AuthenticationScheme = authenticationScheme; BackchannelTimeout = TimeSpan.FromMinutes(1); Caption = OpenIdConnectAuthenticationDefaults.Caption; ProtocolValidator = new OpenIdConnectProtocolValidator(); RefreshOnIssuerKeyNotFound = true; ResponseType = OpenIdConnectResponseTypes.CodeIdToken; Scope = OpenIdConnectScopes.OpenIdProfile; TokenValidationParameters = new TokenValidationParameters(); UseTokenLifetime = true; }
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 { } }
public OpenIdConnectAuthenticationOptions(string authenticationType) : base(authenticationType) { AuthenticationMode = AuthenticationMode.Active; BackchannelTimeout = TimeSpan.FromMinutes(1); Caption = OpenIdConnectAuthenticationDefaults.Caption; ProtocolValidator = new OpenIdConnectProtocolValidator() { RequireStateValidation = false, NonceLifetime = TimeSpan.FromMinutes(15) }; RefreshOnIssuerKeyNotFound = true; ResponseType = OpenIdConnectResponseType.CodeIdToken; Scope = OpenIdConnectScope.OpenIdProfile; SecurityTokenValidator = new JwtSecurityTokenHandler(); RequireHttpsMetadata = true; TokenValidationParameters = new TokenValidationParameters(); UseTokenLifetime = true; CookieManager = new CookieManager(); }
/// <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<Uri>.</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())); }
/// <summary> /// Validates the identity token. /// </summary> /// <param name="idToken">The identifier token.</param> /// <param name="oidcClientId">The oidc client identifier.</param> /// <param name="nonce">The nonce.</param> /// <param name="oidcConfig">The oidc configuration.</param> /// <returns>JwtSecurityToken.</returns> /// <exception cref="System.ArgumentNullException"> /// </exception> private JwtSecurityToken ValidateIdentityToken(string idToken, string oidcClientId, string nonce, OpenIdConnectConfiguration oidcConfig) { if (string.IsNullOrWhiteSpace(idToken)) { throw new ArgumentNullException(nameof(idToken)); } if (string.IsNullOrWhiteSpace(oidcClientId)) { throw new ArgumentNullException(nameof(oidcClientId)); } if (string.IsNullOrWhiteSpace(nonce)) { throw new ArgumentNullException(nameof(nonce)); } if (oidcConfig == null) { throw new ArgumentNullException(nameof(oidcConfig)); } var idTokenValidationParameters = new TokenValidationParameters { ValidAudience = oidcClientId, ValidIssuer = oidcConfig.Issuer, IssuerSigningTokens = oidcConfig.JsonWebKeySet.GetSigningTokens() }; if (IsTokenValidationDisabled) { idTokenValidationParameters.LifetimeValidator = (before, expires, token, parameters) => true; } try { SecurityToken validatedToken; var jwtTokenHandler = new JwtSecurityTokenHandler(); jwtTokenHandler.ValidateToken(idToken, idTokenValidationParameters, out validatedToken); var validationContext = new OpenIdConnectProtocolValidationContext { Nonce = IsTokenValidationDisabled ? null : nonce }; var validatedJwtToken = validatedToken as JwtSecurityToken; var oidcProtocolValidator = new OpenIdConnectProtocolValidator(); if (IsTokenValidationDisabled) { oidcProtocolValidator.RequireNonce = false; } oidcProtocolValidator.Validate(validatedJwtToken, validationContext); return(validatedJwtToken); } catch (Exception ex) { throw new AuthenticationException("An error occurred validating the Id token.", ex); } }
public void OpenIdConnectProtocolValidator_GetSets() { OpenIdConnectProtocolValidator validationParameters = new OpenIdConnectProtocolValidator(); Type type = typeof(OpenIdConnectProtocolValidator); PropertyInfo[] properties = type.GetProperties(); if (properties.Length != 9) { Assert.Fail("Number of properties has changed from 9 to: " + properties.Length + ", adjust tests"); } GetSetContext context = new GetSetContext { PropertyNamesAndSetGetValue = new List <KeyValuePair <string, List <object> > > { new KeyValuePair <string, List <object> >("NonceLifetime", new List <object> { TimeSpan.FromMinutes(60), TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(100) }), new KeyValuePair <string, List <object> >("RequireAcr", new List <object> { false, true, false }), new KeyValuePair <string, List <object> >("RequireAmr", new List <object> { false, true, false }), new KeyValuePair <string, List <object> >("RequireAuthTime", new List <object> { false, true, false }), new KeyValuePair <string, List <object> >("RequireAzp", new List <object> { false, true, false }), new KeyValuePair <string, List <object> >("RequireNonce", new List <object> { true, false, true }), new KeyValuePair <string, List <object> >("RequireSub", new List <object> { false, true, false }), new KeyValuePair <string, List <object> >("RequireTimeStampInNonce", new List <object> { true, false, true }), }, Object = validationParameters, }; TestUtilities.GetSet(context); TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, context.Errors); ExpectedException ee = ExpectedException.ArgumentNullException(); Assert.IsNotNull(validationParameters.HashAlgorithmMap); Assert.AreEqual(validationParameters.HashAlgorithmMap.Count, 9); ee = ExpectedException.ArgumentOutOfRangeException(); try { validationParameters.NonceLifetime = TimeSpan.Zero; ee.ProcessNoException(); } catch (Exception ex) { ee.ProcessException(ex); } }
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); }