private async Task <IActionResult> ScopeAwareAuthentication(string username, string password, Models.User.Action scope) { var user = await _authenticator.Authenticate(username, password, scope); if (user == null) { _response.Errors.Add(Errors.AUTHENTICATION_FAILED, ""); } if (HasErrors()) { return(StatusCode(403, _response)); } _response.Message = Messages.AUTHENTICATION_SUCCEEDED; switch (scope) { case Models.User.Action.ManageApi: case Models.User.Action.ManageDaemon: // Intentionally hidden to keep the JWT length manageable user.Cert = null; user.CertKey = null; var userJson = JsonConvert.SerializeObject(user, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() } ); var claims = new[] { new Claim(ClaimTypes.UserData, userJson), }; var key = _cryptoService.GetJWTSigningKey(); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512); // Hardcoded alg for now, perhaps allow changing later var accessExpires = DateTime.Now.AddMinutes(AppConfig.JWTTokenExpiryInMinutes > 0 ? AppConfig.JWTTokenExpiryInMinutes : 60); // 60 minutes by default var token = new JwtSecurityToken ( // Can't issue aud/iss since we have no idea what the accessing URL will be. // This is not a typical webapp with static `Host` claims: claims, expires: accessExpires, signingCredentials: credentials, issuer: _identityProvider.GetFQDN() ); var accessToken = new Token { token = new JwtSecurityTokenHandler().WriteToken(token), expires = ((DateTimeOffset)accessExpires).ToUnixTimeSeconds() }; var refreshExpires = accessExpires.AddMinutes(AppConfig.JWTRefreshTokenDelta > 0 ? AppConfig.JWTRefreshTokenDelta : 30); var refreshToken = new Token { token = null, expires = ((DateTimeOffset)refreshExpires).ToUnixTimeSeconds() }; _response.Message = Messages.JWT_TOKEN_ISSUED; _response.Result = new AuthResponse { Access = accessToken, Refresh = refreshToken }; break; } return(Ok(_response)); }