public async Task <IActionResult> Confirm([FromBody] ConfirmViewModel vm, CancellationToken cancellationToken) { SecurityToken token; JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); var claims = new JwtSecurityTokenHandler().ValidateToken(vm.JwtTokenString, this._tokenValidationParameters, out token); if (!claims.HasClaim("register", "yes")) { return(this.BadRequest()); } var user = await this._users.FindByIdAsync(claims.GetSubjectId(), cancellationToken); user.Email = claims.Claims.First(c => c.Type == JwtRegisteredClaimNames.Email).Value; user.EmailVerified = true; user.UserName = claims.Claims.First(c => c.Type == JwtRegisteredClaimNames.UniqueName).Value; if (await this._users.CreateAsync(user, nameof(AccountController) + nameof(this.Confirm), cancellationToken) != IdentityResult.Success) { return(this.ServerError(new Exception("Create user failed"))); } return(this.Ok()); }
public async Task <IActionResult> Reset([FromBody] ResetViewModel vm, CancellationToken cancellationToken) { SecurityToken token; JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); var claims = new JwtSecurityTokenHandler().ValidateToken(vm.JwtTokenString, this._tokenValidationParameters, out token); if (!claims.HasClaim("reset_password", "yes") || vm.Password != vm.ConfirmPassword) { return(this.BadRequest()); } var user = await this._users.FindByIdAsync(claims.GetSubjectId(), cancellationToken); if (await this._users.SetUserPasswordAsync(user, vm.Password, cancellationToken)) { return(this.Ok()); } return(this.BadRequest()); }
/// <summary> /// validates a jwtToken based off the options defined in config. /// </summary> /// <param name="token">the token</param> /// <returns>returns an instance of the validated token</returns> private async Task <List <Claim> > ValidateTokenInternal(string token) { if (string.IsNullOrEmpty(token)) { throw new ArgumentNullException(nameof(token)); } var claims = new List <Claim>(); ICollection <SecurityKey> signingKeys = null; OpenIdConnectConfiguration discoveryDocument = null; if (_config.validationOptions.ValidateIssuerSigningKey || _config.enableUserInfoLookup) { //issuer config var issuer = new Uri(_config.issuer); //be default make the discovery url the issuer + OAUTH spec https://tools.ietf.org/html/draft-ietf-oauth-discovery-07#section-3 var discovery = new Uri(issuer, ".well-known/openid-configuration"); //sometimes the issuer can be different than the discovery endpoint. allow for that //is the discovery url absolute? if (Uri.IsWellFormedUriString(_config.discoveryUri, UriKind.Absolute)) { discovery = new Uri(_config.discoveryUri); } else if (Uri.IsWellFormedUriString(_config.discoveryUri, UriKind.Relative)) { discovery = new Uri(issuer, _config.discoveryUri); } var configurationManager = new ConfigurationManager <OpenIdConnectConfiguration>(discovery.AbsoluteUri, new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever { RequireHttps = _config.requireHttpsDiscovery }); //get the public keys from the discovery endpoint //this could be cached to avoid excessive lookup discoveryDocument = await configurationManager.GetConfigurationAsync(default(CancellationToken)).ConfigureAwait(false); signingKeys = discoveryDocument.SigningKeys; } //these are other options for building a key to use to validate if the key is known. #region alternate keys //load from file //IssuerSigningKey = new X509SecurityKey(new X509Certificate2(certLocation)), ///provided signing cert // string X509Cert = "CERT CONTENTS"; //X509Certificate2 DefaultCert_Public_2048 = new X509Certificate2(Convert.FromBase64String(X509Cert)); //X509SecurityKey DefaultX509Key_Public_2048 = new X509SecurityKey(DefaultCert_Public_2048); //SigningCredentials DefaultX509SigningCreds_Public_2048_RsaSha2_Sha2 = new SigningCredentials(DefaultX509Key_Public_2048, SecurityAlgorithms.RsaSha256Signature); ///Alternative asyematric public key build. Typeically gathered from discovery endpoint //var e = Base64Url.Decode("AQAB"); //var n = Base64Url.Decode("wKchfRYocmVQW2tEbagQYLJDwkYOyU2Nf1vomzHZGdjeIyyvexLjW6YW6kCnNG5-I2Lm67pTUE8fBI7gL68whkUYsXCx7lXgo3Snx17_xwPBPdmiI42Xx-IAU-D8YvO7aOaYwbUqwiPrDG5GeaaMHqqbNu4G4vrKptkgBvUSSbNWfqmkg3e-BdrjLIlkyqMmpGuAokMl_eHH90_Av_D27Nw8RzhsGezlThQUte-MXd5oFLr4IT730SKRksR1Clm--CGIc7rr79oaVF1OZw44cgl1DsezsmKw9MQRTe8Mr_j4l0i6RPuVdm_LzUpE5zoStb1ta5b6RBekO1F5ZEjNUQ"); //var signingKey = new RsaSecurityKey(new RSAParameters { Exponent = e, Modulus = n }) { // KeyId = "2c4147d18d355afaf60bce38220898f2" //}; #endregion var validationParameters = new TokenValidationParameters { ValidateIssuer = _config.validationOptions.validateIssuer, RequireSignedTokens = _config.validationOptions.ValidateIssuerSigningKey, ValidateIssuerSigningKey = _config.validationOptions.ValidateIssuerSigningKey, ValidateLifetime = _config.validationOptions.ValidateLifetime, ValidateAudience = _config.validationOptions.ValidateAudience, // Allow for some drift in server time // (a lower value is better; we recommend five minutes or less) ClockSkew = TimeSpan.FromMinutes(5), }; if (_config.validationOptions.validateIssuer) { validationParameters.ValidIssuer = _config.issuer; } if (_config.validationOptions.ValidateIssuerSigningKey) { validationParameters.IssuerSigningKeys = signingKeys; } else { validationParameters.SignatureValidator = (t, opt) => { var jwt = new JwtSecurityToken(t); return(jwt); } }; if (_config.validationOptions.ValidateAudience) { validationParameters.ValidAudiences = _config.audiences; } var principal = new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var rawValidatedToken); JwtSecurityToken newToken = (JwtSecurityToken)rawValidatedToken; claims.AddRange(newToken.Claims); //if there is a 'sub' claim on the token query for additional claims if (principal.HasClaim("scope", "openid") && _config.enableUserInfoLookup) { //look up user information to gather additional claims HttpClient httpClient = HttpClientManager.Instance.HttpClient; using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, discoveryDocument.UserInfoEndpoint)) { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); using (var response = await httpClient.SendAsync(requestMessage).ConfigureAwait(false)) { if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var userclaims = JsonConvert.DeserializeObject <Dictionary <string, object> >(content); foreach (var c in userclaims) { if (c.Value.GetType().IsArray) { foreach (var v in (string[])c.Value) { claims.Add(new Claim(c.Key, v, ClaimValueTypes.String, issuer: newToken.Issuer)); } } claims.Add(new Claim(c.Key, c.Value.ToString(), ClaimValueTypes.String, issuer: newToken.Issuer)); } } } } } return(claims); }