public async Task <IActionResult> CreateEmptyPatrol(Models.Patrol patrolSetup) { //TODO: update to also update jwt var patrol = await _patrolCreationService.CreateNewPatrol(User.UserId(), patrolSetup); //TODO: we don't need this once the UI uses the JWT var patrols = await _patrolRepository.GetPatrolsForUser(User.UserId()); //refresh the users jwt to match the above change Response.SendNewToken(await _authenticationService.IssueJwtToUser(User.UserId(), User.TokenGuid())); return(Ok(patrols)); }
protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { var now = _systemClock.UtcNow.UtcDateTime; if (!Request.Headers.ContainsKey("Authorization")) { Logger.LogError("Missing Authorization Header"); return(AuthenticateResult.Fail("Missing Authorization Header")); } ClaimsPrincipal principal = null; try { AuthenticationHeaderValue authenticationHeader; if (AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out authenticationHeader)) { if (authenticationHeader.Scheme == "Basic") { var credentialBytes = Convert.FromBase64String(authenticationHeader.Parameter); var credentialString = Encoding.UTF8.GetString(credentialBytes); if (credentialString.Contains(":")) { var credentials = credentialString.Split(new[] { ':' }, 2); var email = credentials[0]; var password = credentials[1]; var user = await _authenticationService.AuthenticateUserWithPassword(email, password); if (user == null) { //bad password Logger.LogError("Invalid Username or password"); return(AuthenticateResult.Fail("Invalid Username or Password")); } else { //make a token and put it in the response header? Logger.LogInformation("Authenticated User {@email} via email/password", user.Email); var jwt = await _authenticationService.IssueJwtToUser(user.Id); principal = _authenticationService.ValidateSignedJwtToken(jwt); Response.Headers.Add("Authorization", "Token " + jwt); } } } else if (authenticationHeader.Scheme == "Token" || authenticationHeader.Scheme == "Bearer") //TODO: remove "Token" { if ((new JwtSecurityTokenHandler()).CanReadToken(authenticationHeader.Parameter)) { var jwtPrincipal = _authenticationService.ValidateSignedJwtToken(authenticationHeader.Parameter); var parsed = jwtPrincipal.ParseAllClaims(); //TODO: update this so that only superseded/expired token are in the db, "good" tokens will not be var token = await _tokenRepository.GetToken(parsed.Token.TokenGuid); if (token == null || (token.ExpiredAt.HasValue && token.ExpiredAt < now)) { //note we do NOT set the principle, it's expired so we let it fail as invalid } else if ((parsed.Minimal.HasValue && parsed.Minimal.Value) || (token.SupersededAt.HasValue && token.SupersededAt < now)) { //token is valid, but needs to be updated due to some change that was made to data contained therein //OR the token is a minimal one which needs to be repalced with a "full" token var refreshedJwt = await _authenticationService.IssueJwtToUser(parsed.User.Id, token.TokenGuid); //send the updated token back to client Response.Headers.Add("Authorization", "Token " + refreshedJwt); principal = _authenticationService.ValidateSignedJwtToken(refreshedJwt); } else { principal = jwtPrincipal; } Logger.LogInformation("Authenticated User {@id} via bearer token {@tokenGuid}", parsed.User.Id, parsed.Token.TokenGuid); } } else { Logger.LogError("Invalid Authorization Header"); //it's not a token and it's not a basic, what is it? return(AuthenticateResult.Fail("Invalid Authorization Header")); } } else { Logger.LogError("Invalid Authorization Header"); //we can't understand the auth header return(AuthenticateResult.Fail("Invalid Authorization Header")); } } catch (Exception ex) { Logger.LogError("Exception in Authorization {@ex}", ex); //some exception we weren't ready for, likely a malformed header return(AuthenticateResult.Fail("Invalid Authorization Header")); } if (principal == null) { //this shouldn't actually happen, but just in case Logger.LogError("Invalid Username or Password"); return(AuthenticateResult.Fail("Invalid Username or Password")); } var ticket = new AuthenticationTicket(principal, Scheme.Name); return(AuthenticateResult.Success(ticket)); }