/// <summary> /// Acquires the access token and related parameters that go into the formulation of the token endpoint's response to a /// client. /// </summary> /// <param name="accessTokenRequestMessage"> /// Details regarding the resources that the access token will grant access to, and the identity of the client /// that will receive that access. /// Based on this information the receiving resource server can be determined and the lifetime of the access /// token can be set based on the sensitivity of the resources. /// </param> /// <returns>A non-null parameters instance that DotNetOpenAuth will dispose after it has been used.</returns> public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage) { TimeSpan clientApplicationLifetime = GetClientLifetime(accessTokenRequestMessage); var accessToken = new AuthorizationServerAccessToken { // Note: all other fields are assigned by IsAuthorizationValid() (i.e. ClientIdentifier, Scope, User and UtcIssued) // Set the crypto keys for accessing the secured services (assume there is only one secured service) AccessTokenSigningKey = CryptoKeyProvider.GetCryptoKey(CryptoKeyType.AuthZServer).PrivateEncryptionKey, ResourceServerEncryptionKey = GetRequestedSecureResourceCryptoKey(), // Set the limited lifetime of the token Lifetime = (clientApplicationLifetime != TimeSpan.Zero) ? clientApplicationLifetime : TimeSpan.FromMinutes(DefaultLifetime), }; // Insert user specific information string username = GetUserFromAccessTokenRequest(accessTokenRequestMessage); if (username.HasValue()) { IUserAuthInfo user = GetUserAuthInfo(username); if (user != null) { accessToken.ExtraData.Add(new KeyValuePair <string, string>( RequireAuthorizationAttribute.ExtraDataRoles, String.Join(@",", user.Roles))); } } return(new AccessTokenResult(accessToken)); }
/// <summary> /// Determines whether a given set of resource owner credentials is valid based on the authorization server's user /// database /// and if so records an authorization entry such that subsequent calls to <see cref="IsAuthorizationValid" /> would /// return <c>true</c>. /// </summary> /// <param name="userName">Username on the account.</param> /// <param name="password">The user's password.</param> /// <param name="accessRequest"> /// The access request the credentials came with. /// This may be useful if the authorization server wishes to apply some policy based on the client that is making the /// request. /// </param> /// <returns>A value that describes the result of the authorization check.</returns> /// <exception cref="NotSupportedException"> /// May be thrown if the authorization server does not support the resource owner password credential grant type. /// </exception> public AutomatedUserAuthorizationCheckResponse CheckAuthorizeResourceOwnerCredentialGrant(string userName, string password, IAccessTokenRequest accessRequest) { Guard.NotNullOrEmpty(() => userName, userName); Guard.NotNullOrEmpty(() => password, password); Guard.NotNull(() => accessRequest, accessRequest); bool approved = false; //Ensure client exists if (IsClientExist(accessRequest.ClientIdentifier)) { // Ensure user exists IUserAuthInfo user = UserAccountStore.GetUserAuthInfo(userName); if (user != null) { if (IsValidScope(accessRequest)) { if (user.VerifyPassword(password)) { approved = true; //TODO: audit the passed authentication } //TODO: audit the failed authentication } } } return(new AutomatedUserAuthorizationCheckResponse(accessRequest, approved, (approved) ? userName : null)); }
/// <summary> /// Creates a new instance of the <see cref="ClientUserInfo" /> class. /// </summary> public ClientUserInfo(IUserAuthInfo authInfo, string password, string emailDomain) { Guard.NotNull(() => authInfo, authInfo); Guard.NotNullOrEmpty(() => password, password); Guard.NotNullOrEmpty(() => emailDomain, emailDomain); AuthInfo = authInfo; Password = password; this.emailDomain = emailDomain; }
public void WhenGetUserAuthInfoWithUnknownUserName_ThenReturnsNull() { manager.Setup( uam => uam.ListUserAccounts(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(Enumerable.Empty <IUserAccount>()); IUserAuthInfo result = store.GetUserAuthInfo("foo"); Assert.Null(result); }
public void reading_IUserAuthInfo_for_an_unexisting_user_or_Anonymous_returns_null() { var p = TestHelper.StObjMap.Default.Obtain <Package>(); using (var ctx = new SqlStandardCallContext()) { IUserAuthInfo info = p.ReadUserAuthInfo(ctx, 1, int.MaxValue); info.Should().BeNull(); info = p.ReadUserAuthInfo(ctx, 1, 0); info.Should().BeNull(); } }
public void WhenGetUserAuthInfoProfileWithKnownUserName_ThenReturnsUserAuthInfo() { var userAccount = new UserAccount { Id = "fooid", Username = "******", PasswordHash = "bar", }; manager.Setup( uam => uam.ListUserAccounts(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .Returns(new[] { userAccount }); IUserAuthInfo result = store.GetUserAuthInfo("foo"); Assert.Equal("bar", result.PasswordHash); Assert.Equal("foo2", result.Username); }
static public void StandardTestForGenericAuthenticationProvider( Package auth, string schemeOrProviderName, Func <int, string, object> payloadForCreateOrUpdate, Func <int, string, object> payloadForLogin, Func <int, string, object> payloadForLoginFail ) { var user = TestHelper.StObjMap.Default.Obtain <Actor.UserTable>(); IGenericAuthenticationProvider g = auth.FindProvider(schemeOrProviderName); using (var ctx = new SqlStandardCallContext()) { string userName = Guid.NewGuid().ToString(); int userId = user.CreateUser(ctx, 1, userName); using (TestHelper.Monitor.OpenInfo($"StandardTest for generic {schemeOrProviderName} with userId:{userId} and userName:{userName}.")) { IUserAuthInfo info = auth.ReadUserAuthInfo(ctx, 1, userId); info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser without login")) { g.CreateOrUpdateUser(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName)).OperationResult.Should().Be(UCResult.Created); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Count.Should().Be(0, "Still no scheme since we did not use WithActualLogin."); g.LoginUser(ctx, payloadForLogin(userId, userName), actualLogin: false).UserId.Should().Be(userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().BeEmpty("Still no scheme since we challenge login but not use WithActualLogin."); g.LoginUser(ctx, payloadForLogin(userId, userName)).UserId.Should().Be(userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Count.Should().Be(1); info.Schemes[0].Name.Should().StartWith(g.ProviderName); info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName); info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000); g.DestroyUser(ctx, 1, userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser WithActualLogin")) { info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); var result = g.CreateOrUpdateUser(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName), UCLMode.CreateOnly | UCLMode.WithActualLogin); result.OperationResult.Should().Be(UCResult.Created); result.LoginResult.UserId.Should().Be(userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().HaveCount(1); info.Schemes[0].Name.Should().StartWith(g.ProviderName); info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName); info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000); g.LoginUser(ctx, payloadForLoginFail(userId, userName)).UserId.Should().Be(0); g.DestroyUser(ctx, 1, userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("Login for an unregistered user.")) { info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); var result = g.LoginUser(ctx, payloadForLogin(userId, userName)); result.IsSuccess.Should().BeFalse(); result.UserId.Should().Be(0); result.FailureCode.Should().Be((int)KnownLoginFailureCode.UnregisteredUser); result.FailureReason.Should().Be("Unregistered user."); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().BeEmpty(); g.DestroyUser(ctx, 1, userId); info = auth.ReadUserAuthInfo(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("Invalid payload MUST throw an ArgumentException.")) { g.Invoking(sut => sut.CreateOrUpdateUser(ctx, 1, userId, DBNull.Value)).Should().Throw <ArgumentException>(); g.Invoking(sut => sut.LoginUser(ctx, DBNull.Value)).Should().Throw <ArgumentException>(); } } user.DestroyUser(ctx, 1, userId); } }
static public async Task StandardTestForGenericAuthenticationProviderAsync( Package auth, string schemeOrProviderName, Func <int, string, object> payloadForCreateOrUpdate, Func <int, string, object> payloadForLogin, Func <int, string, object> payloadForLoginFail ) { var user = TestHelper.StObjMap.Default.Obtain <Actor.UserTable>(); IGenericAuthenticationProvider g = auth.FindProvider(schemeOrProviderName); using (var ctx = new SqlStandardCallContext()) { string userName = Guid.NewGuid().ToString(); int userId = await user.CreateUserAsync(ctx, 1, userName); using (TestHelper.Monitor.OpenInfo($"StandardTestAsync for generic {schemeOrProviderName} with userId:{userId} and userName:{userName}.")) { IUserAuthInfo info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser without login.")) { (await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate(userId, userName))).OperationResult.Should().Be(UCResult.Created); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty("Still no scheme since we did not use WithLogin."); (await g.LoginUserAsync(ctx, payloadForLogin(userId, userName), actualLogin: false)).UserId.Should().Be(userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty("Still no scheme since we challenge login but not use WithLogin."); (await g.LoginUserAsync(ctx, payloadForLogin(userId, userName))).UserId.Should().Be(userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().HaveCount(1); info.Schemes[0].Name.Should().StartWith(g.ProviderName); info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName); info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000); await g.DestroyUserAsync(ctx, 1, userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("CreateOrUpdateUser WithActualLogin.")) { info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); var result = await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate( userId, userName ), UCLMode.CreateOnly | UCLMode.WithActualLogin); result.OperationResult.Should().Be(UCResult.Created); result.LoginResult.UserId.Should().Be(userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Count.Should().Be(1); info.Schemes[0].Name.Should().StartWith(g.ProviderName); info.Schemes[0].Name.Should().BeEquivalentTo(schemeOrProviderName); info.Schemes[0].LastUsed.Should().BeCloseTo(DateTime.UtcNow, 1000); (await g.LoginUserAsync(ctx, payloadForLoginFail(userId, userName))).UserId.Should().Be(0); await g.DestroyUserAsync(ctx, 1, userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("Login for an unregistered user.")) { info.UserId.Should().Be(userId); info.UserName.Should().Be(userName); info.Schemes.Should().BeEmpty(); var result = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName )); result.IsSuccess.Should().BeFalse(); result.UserId.Should().Be(0); result.FailureCode.Should().Be((int)KnownLoginFailureCode.UnregisteredUser); result.FailureReason.Should().Be("Unregistered user."); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty(); await g.DestroyUserAsync(ctx, 1, userId); info = await auth.ReadUserAuthInfoAsync(ctx, 1, userId); info.Schemes.Should().BeEmpty(); } using (TestHelper.Monitor.OpenInfo("Invalid payload MUST throw an ArgumentException.")) { g.Awaiting(sut => sut.CreateOrUpdateUserAsync(ctx, 1, userId, DBNull.Value)).Should().Throw <ArgumentException>(); g.Awaiting(sut => sut.LoginUserAsync(ctx, DBNull.Value)).Should().Throw <ArgumentException>(); } using (TestHelper.Monitor.OpenInfo("Injecting disabled user in sAuthUserOnLogin.")) using (auth.Database.TemporaryTransform(@" create transformer on CK.sAuthUserOnLogin as begin inject ""set @FailureCode = 6; -- GloballyDisabledUser"" into ""CheckLoginFailure""; end ")) { UCLResult result = await g.CreateOrUpdateUserAsync(ctx, 1, userId, payloadForCreateOrUpdate( userId, userName ), UCLMode.CreateOnly | UCLMode.WithActualLogin); result.OperationResult.Should().Be(UCResult.Created); result.LoginResult.UserId.Should().Be(0); result.LoginResult.IsSuccess.Should().BeFalse(); result.LoginResult.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser); LoginResult login = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName )); login.IsSuccess.Should().BeFalse(); login.UserId.Should().Be(0); login.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser); login = await g.LoginUserAsync(ctx, payloadForLogin( userId, userName ), actualLogin : false); login.IsSuccess.Should().BeFalse(); login.UserId.Should().Be(0); login.FailureCode.Should().Be((int)KnownLoginFailureCode.GloballyDisabledUser); } } await user.DestroyUserAsync(ctx, 1, userId); } }