public string FindErrors(HttpContext context, ArgonautOptions options) { if (!context.Request.Method.Equals("POST")) { return("The request method must be POST."); } if (context.Request.Form == null) { return("The request content type must be application/x-www-form-urlencoded."); } if (!context.Request.HasFormContentType) { return("The request content type must be application/x-www-form-urlencoded."); } if (!context.Request.Form.ContainsKey("username")) { return("A username form field is required."); } if (!context.Request.Form.ContainsKey("password")) { return("A password form field is required."); } if (!context.Request.Form.ContainsKey("audience")) { return("An audience form field is required."); } return(""); }
public async Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options) { var username = context.Request.Form["username"]; var password = context.Request.Form["password"]; var audienceId = context.Request.Form["audience"]; var userValidation = options.ValidateUser.Invoke(username, password, audienceId); //Passback ArgonautUser, which should include audience. if (!userValidation.Validated) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; var msg = ""; if (!string.IsNullOrEmpty(userValidation.ValidationFailureUserMessage)) { msg = userValidation.ValidationFailureUserMessage; } else { msg = "Invalid username, password, or audience."; } await context.Response.WriteAsync(msg); return; } _jwtBuilder = JWTBuilder.New(userValidation.Audience); foreach (var c in userValidation.Claims) { _jwtBuilder.AddClaim(c); } await GenerateAccessToken(context, username, options); }
public PreflightPolicy(RequestDelegate next, IOptions <ArgonautOptions> options) { if (options == null) { throw new ArgumentNullException(nameof(ArgonautOptions)); } _next = next; _options = options.Value; }
public FindRequestType(RequestDelegate next, IOptions <ArgonautOptions> options) { if (options == null) { throw new ArgumentNullException(nameof(ArgonautOptions)); } _options = options.Value; _next = next; }
public string FindErrors(HttpContext context, ArgonautOptions options) { if (context.Request.Headers.ContainsKey("authorization") && !context.Request.Headers["authorization"].ToString().Contains("Bearer ")) { return("The authorization field needs to be formatted as Bearer [access_token]."); } return(""); }
public string FindErrors(HttpContext context, ArgonautOptions options) { //Check to see if the user is attemping to request an access token by checking if the 'grant_type' parameter exists, even though the request type could not be found. if (!context.Request.HasFormContentType) { return(""); } if (context.Request.Form.ContainsKey("grant_type")) { return("The request is not properly formatted."); } //End check return(""); }
public void Validate(HttpContext context, ArgonautOptions options) { var origin = context.Request.Headers["Origin"].ToString().ToLower(); var audienceId = context.Request.Form["audience"].ToString().ToLower(); var audFound = options.Audiences.Where(l => l.Id.ToLower() == audienceId).FirstOrDefault(); if (audFound == null) { return; } var allowedOrigins = audFound.AllowedOrigins.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray(); if (allowedOrigins.Contains("*") || allowedOrigins.Contains(origin)) { context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() }); } }
public void Validate(HttpContext context, ArgonautOptions options) { var authHeader = context.Request.Headers.Where(l => l.Key.ToLower() == "authorization").FirstOrDefault(); var accessToken = authHeader.Value.ToString().Replace("Bearer ", ""); var audRequested = GetAudienceIdFromAccessToken(accessToken).ToLower(); var audFound = options.Audiences.Where(l => l.Id.ToLower() == audRequested).FirstOrDefault(); if (audFound == null) { return; //OR Return 404 - Audience not found?? Decided against this on the off chance it could be used to fish for allowed audiences. } var origin = context.Request.Headers["Origin"].ToString().ToLower(); var allowedOrigins = audFound.AllowedOrigins.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray(); if (allowedOrigins.Contains("*") || allowedOrigins.Contains(origin)) { context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() }); } }
private async Task GenerateAccessToken(HttpContext context, string subject, ArgonautOptions options) //,User user { _jwtBuilder.Subject = subject; _jwtBuilder.Expiration = TimeSpan.FromMinutes(options.AccessTokenLifetimeMinutes); _jwtBuilder.VisualiseClaims = options.VisualiseClaims; _jwtBuilder.Build(); var response = _jwtBuilder.GetWebResponse(); var rt = _jwtBuilder.GetRefreshToken(); rt.EncryptTicket(_encryptor); //Generate event for client to save refresh token to persistence options.RefreshTokenGenerated( new Internal.Model.RefreshToken(rt.Id, rt.Subject, rt.AudienceId, rt.IssuedUtc, rt.ExpiresUtc, rt.ProtectedTicket) ); context.Response.ContentType = "application/json"; await context.Response.WriteAsync(JsonConvert.SerializeObject(response, new JsonSerializerSettings { Formatting = Formatting.Indented })); }
public string FindErrors(HttpContext context, ArgonautOptions options) { if (!context.Request.Method.Equals("POST")) { return("The request method must be POST."); } if (context.Request.Form == null) { return("The request content type must be application/x-www-form-urlencoded."); } if (!context.Request.HasFormContentType) { return("The request content type must be application/x-www-form-urlencoded."); } if (!context.Request.Form.ContainsKey("refresh_token")) { return("A refresh_token form field is required."); } return(""); }
public Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options) => next(context);
public async Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options) { var rtFromRequest = context.Request.Form["refresh_token"]; var hashedRefreshTokenId = Argonaut.Internal.Hashing.GetHash(rtFromRequest); var persistenceResponse = options.RefreshAccessToken(hashedRefreshTokenId); //Client returns refresh token model with encrpted ticket. if (persistenceResponse == null) { await RespondRefreshTokenInvalid(context); return; } if (persistenceResponse.RefreshToken == null) { await RespondRefreshTokenInvalid(context); return; } if (persistenceResponse.Audience == null) { await RespondRefreshTokenInvalid(context); return; } //Map to domain refresh token Domain.RefreshToken rt = Domain.RefreshToken.New( persistenceResponse.RefreshToken.Id, persistenceResponse.RefreshToken.Subject, persistenceResponse.RefreshToken.AudienceId, persistenceResponse.RefreshToken.ProtectedTicket, persistenceResponse.RefreshToken.IssuedUtc, persistenceResponse.RefreshToken.ExpiresUtc ); var nowUtc = DateTime.UtcNow; //TODO: Could do with moving to interface if (nowUtc > rt.ExpiresUtc) { await RespondRefreshTokenInvalid(context); return; } try { rt.DecryptTicket(_encryptor, rtFromRequest.ToString()); } catch { context.Response.StatusCode = 401; await context.Response.WriteAsync("Persisted refresh token failed decryption - Log in using username and password."); return; } if (rt.ProtectedTicket == null) { await RespondRefreshTokenInvalid(context); return; } var vp = new JWTValidationParametersGenerator(persistenceResponse.Audience).SecretOnly(); var handler = new JwtSecurityTokenHandler(); Microsoft.IdentityModel.Tokens.SecurityToken validatedToken = null; try { handler.ValidateToken(rt.ProtectedTicket, vp, out validatedToken); } catch { await RespondRefreshTokenInvalid(context); return; } if (validatedToken == null) { await RespondRefreshTokenInvalid(context); return; } var jwt = validatedToken as System.IdentityModel.Tokens.Jwt.JwtSecurityToken; var sub = jwt.Claims.Where(l => l.Type == "sub").FirstOrDefault().Value; var claimsToUse = jwt.Claims.ExcludeDefaultAccessTokenClaims(); _jwtBuilder = JWTBuilder.New(persistenceResponse.Audience); _jwtBuilder.AddClaims(claimsToUse); await GenerateAccessToken(context, sub, options); }
public void Validate(HttpContext context, ArgonautOptions options) /*Do nothing*/ }
/// <summary> /// Always allow origin for refresh token requests as the associated audience can only be found by a trip to the database. /// Origin still needed for access token and any data. /// </summary> public void Validate(HttpContext context, ArgonautOptions options) => context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() });