public async Task <ServiceResponse <JwtTokens> > Login() { if (!HttpListener.IsSupported) { throw new HttpListenerNotSupportedException(); } var listener = new HttpListener(); listener.Prefixes.Add($"{this.configuration.CallbackUrl}/"); listener.Start(); HttpListenerContext requestContext = await this.HandleAuthCallback(listener); HttpListenerRequest httpRequest = requestContext.Request; string authCode = httpRequest.QueryString["code"]; JwtTokens tokens = await this.RequestJwtTokens(authCode); if (tokens == null) { await this.RespondWithFailedLogin(requestContext); listener.Stop(); return(null); } await this.RespondWithSuccessfulLogin(requestContext); listener.Stop(); return(new ServiceResponse <JwtTokens>(tokens)); }
public async Task AuthorizeUser_ReturnsTokens() { // Arrange var tokenFactory = new TestTokenFactory(); string id_token = tokenFactory.GetIdToken(true); string access_token = tokenFactory.GetAccessToken(false); JwtTokens tokens = new JwtTokens { AccessToken = access_token, IdToken = id_token }; Mock <ITokenRepository> repositoryMock = new Mock <ITokenRepository>(); Mock <ILogger <OAuthAuthorizationService> > loggerMock = new Mock <ILogger <OAuthAuthorizationService> >(); Mock <ILoginService> loginMock = new Mock <ILoginService>(); loginMock .Setup(mock => mock.Login()) .Returns(Task.FromResult(new ServiceResponse <JwtTokens>(tokens))); IAccountService accountService = new OAuthAuthorizationService(repositoryMock.Object, loginMock.Object, loggerMock.Object); // Act ServiceResponse <LoginResponse> authResponse = await accountService.AuthorizeUser(); // Assert Assert.IsNotNull(authResponse.Data.AccessToken.UserId); Assert.AreNotEqual(0, authResponse.Data.AccessToken.Scopes.Length); Assert.AreNotEqual(0, authResponse.Data.AccessToken.ExpiresAt); // Ensure we cleaned up previous auth sessions, attempted to perform a login and then saved the new auth tokens. repositoryMock.Verify(repo => repo.DeleteToken(), Times.Once); repositoryMock.Verify(repo => repo.SaveToken(It.IsAny <JwtTokens>()), Times.Once); loginMock.Verify(repo => repo.Login(), Times.Once); }
public async Task <ServiceResponse <LoginResponse> > AuthorizeUser() { await this.DeauthorizeUser(); ServiceResponse <JwtTokens> loginResponse = await this.loginService.Login(); if (loginResponse?.Data == null) { ResponseError loginError = new ResponseError(SDKErrors.LoginFailed.Code, SDKErrors.LoginFailed.Message); return(new ServiceResponse <LoginResponse>(loginError)); } JwtTokens jwtTokens = loginResponse.Data; try { await this.tokenRepository.SaveToken(loginResponse.Data); return(new ServiceResponse <LoginResponse>(new LoginResponse(jwtTokens))); } catch (Exception) { var saveTokenError = new ResponseError(SDKErrors.SaveTokenFailed.Code, SDKErrors.SaveTokenFailed.Message); return(new ServiceResponse <LoginResponse>(saveTokenError)); } }
public Task <JwtTokens> GetToken() { // Get a reference to the database that stores the tokens. ILiteDatabase database = this.databaseFactory.GetDatabase(DatabaseName); JwtTokens protectedTokens = null; using (database) { ILiteCollection <JwtTokens> tokenCollection = database.GetCollection <JwtTokens>(TokenCollection); // Find the access token record. There should only ever be 1 record in the database at a time. protectedTokens = tokenCollection.FindOne(token => !string.IsNullOrEmpty(token.AccessToken)); if (protectedTokens == null) { return(Task.FromResult <JwtTokens>(null)); } } // Unprotect the tokens and return them. try { JwtTokens unprotectedTokens = this.UnprotectTokens(protectedTokens); return(Task.FromResult(unprotectedTokens)); } catch (CryptographicException) { this.logger.LogError("Failed to unprotect tokens. Potentially tampered with."); return(Task.FromResult <JwtTokens>(null)); } }
public async Task <ServiceResponse <JwtTokens> > GetTokens() { this.logger.LogInformation("Fetching previously retrieved tokens."); JwtTokens token = await this.tokenRepository.GetToken(); if (token == null) { this.logger.LogError("User is not currently logged into their account."); var getTokenFailed = new ResponseError(SDKErrors.LoadTokensFailed.Code, SDKErrors.LoadTokensFailed.Message); return(new ServiceResponse <JwtTokens>(getTokenFailed)); } return(new ServiceResponse <JwtTokens>(token)); }
public void JsonDeserialization_AssignsValues() { // Arrange var tokenFactory = new TestTokenFactory(); string idTokenJson = tokenFactory.GetIdToken(false); string accessTokenJson = tokenFactory.GetAccessToken(false); string jwtTokenJson = JsonSerializer.Serialize(new { id_token = idTokenJson, access_token = accessTokenJson }); // Act JwtTokens jwtTokens = Newtonsoft.Json.JsonConvert.DeserializeObject <JwtTokens>(jwtTokenJson); // Assert Assert.AreEqual(idTokenJson, jwtTokens.IdToken, "Expected the id_token value to have been assigned"); Assert.AreEqual(accessTokenJson, jwtTokens.AccessToken, "Expected the access_token value to have been assigned"); }
public void AccessToken_HasExpiredToken() { // Arrange var tokenFactory = new TestTokenFactory(); string idTokenJson = tokenFactory.GetIdToken(false); string accessTokenJson = tokenFactory.GetAccessToken(true); string jwtTokenJson = JsonSerializer.Serialize(new { id_token = idTokenJson, access_token = accessTokenJson }); JwtTokens jwtTokens = Newtonsoft.Json.JsonConvert.DeserializeObject <JwtTokens>(jwtTokenJson); // Act bool isExpired = jwtTokens.IsAccessTokenExpired(); // Assert Assert.IsTrue(isExpired); }
public void IdToken_GetTokenReturnsValue() { // Arrange var tokenFactory = new TestTokenFactory(); string idTokenJson = tokenFactory.GetIdToken(true); string accessTokenJson = tokenFactory.GetAccessToken(false); string jwtTokenJson = JsonSerializer.Serialize(new { id_token = idTokenJson, access_token = accessTokenJson }); JwtTokens jwtTokens = Newtonsoft.Json.JsonConvert.DeserializeObject <JwtTokens>(jwtTokenJson); // Act IdToken idToken = jwtTokens.GetIdToken(); // Assert Assert.IsNotNull(idToken.UserId); Assert.IsNotNull(idToken.Username); Assert.AreNotEqual(0, idToken.ExpiresAt); }
public Task SaveToken(JwtTokens jwtToken) { if (jwtToken is null || string.IsNullOrEmpty(jwtToken.AccessToken) || string.IsNullOrEmpty(jwtToken.IdToken) || string.IsNullOrEmpty(jwtToken.RefreshToken)) { throw new ArgumentNullException(nameof(jwtToken)); } JwtTokens protectedTokens = this.ProtectTokens(jwtToken); ILiteDatabase database = this.databaseFactory.GetDatabase(DatabaseName); using (database) { ILiteCollection <JwtTokens> tokenCollection = database.GetCollection <JwtTokens>(TokenCollection); tokenCollection.Insert(protectedTokens); } return(Task.CompletedTask); }
private JwtTokens UnprotectTokens(JwtTokens protectedTokens) { // Create a Protector and start unprotecting the tokens IDataProtector authProtector = this.protectionProvider.CreateProtector(TokenProtector); IDataProtector accessTokenProtector = authProtector.CreateProtector(AccessTokenProtector); string accessToken = accessTokenProtector.Unprotect(protectedTokens.AccessToken); IDataProtector idTokenProtector = authProtector.CreateProtector(IdTokenProtector); string idToken = idTokenProtector.Unprotect(protectedTokens.IdToken); IDataProtector refreshTokenProtector = authProtector.CreateProtector(RefreshTokenProtector); string refreshToken = refreshTokenProtector.Unprotect(protectedTokens.RefreshToken); // Return the unprotected tokens for use. return(new JwtTokens { AccessToken = accessToken, IdToken = idToken, RefreshToken = refreshToken, }); }
public async Task AuthorizeUser_ReturnsErrorWhenSavingFails() { // Arrange var tokenFactory = new TestTokenFactory(); string id_token = tokenFactory.GetIdToken(true); string access_token = tokenFactory.GetAccessToken(false); JwtTokens tokens = new JwtTokens { AccessToken = access_token, IdToken = id_token }; Mock <ILogger <OAuthAuthorizationService> > loggerMock = new Mock <ILogger <OAuthAuthorizationService> >(); Mock <ITokenRepository> repositoryMock = new Mock <ITokenRepository>(); repositoryMock .Setup(repo => repo.SaveToken(It.IsAny <JwtTokens>())) .Throws <Exception>(); Mock <ILoginService> loginMock = new Mock <ILoginService>(); loginMock .Setup(mock => mock.Login()) .Returns(Task.FromResult(new ServiceResponse <JwtTokens>(tokens))); IAccountService accountService = new OAuthAuthorizationService(repositoryMock.Object, loginMock.Object, loggerMock.Object); // Act ServiceResponse <LoginResponse> authResponse = await accountService.AuthorizeUser(); // Assert Assert.IsNull(authResponse.Data); Assert.AreEqual(1, authResponse.Errors.Length); Assert.AreEqual(SDKErrors.SaveTokenFailed.Code, authResponse.Errors[0].Code); Assert.AreEqual(SDKErrors.SaveTokenFailed.Message, authResponse.Errors[0].Message); repositoryMock.Verify(repo => repo.DeleteToken(), Times.Once); repositoryMock.Verify(repo => repo.SaveToken(It.IsAny <JwtTokens>()), Times.Once); loginMock.Verify(repo => repo.Login(), Times.Once); }
private JwtTokens ProtectTokens(JwtTokens jwtTokens) { IDataProtector authProtector = this.protectionProvider.CreateProtector(TokenProtector); // Protect Access Token with a unique protector IDataProtector accessTokenProtector = authProtector.CreateProtector(AccessTokenProtector); string encryptedAccessToken = accessTokenProtector.Protect(jwtTokens.AccessToken); // Protect Id Token with a unique protector IDataProtector idTokenProtector = authProtector.CreateProtector(IdTokenProtector); string encryptedIdToken = idTokenProtector.Protect(jwtTokens.IdToken); // Protect Refresh Token with a unique protector IDataProtector refreshTokenProtector = authProtector.CreateProtector(RefreshTokenProtector); string encryptedRefreshToken = refreshTokenProtector.Protect(jwtTokens.RefreshToken); return(new JwtTokens { AccessToken = encryptedAccessToken, IdToken = encryptedIdToken, RefreshToken = encryptedRefreshToken, }); }