Merge pull request #2304 from stianst/KEYCLOAK-2513

KEYCLOAK-2513 Add test for direct grant with OTP
This commit is contained in:
Stian Thorgersen 2016-03-01 19:33:45 +01:00
commit db5efdca64
2 changed files with 73 additions and 2 deletions

View file

@ -205,6 +205,10 @@ public class OAuthClient {
return doGrantAccessTokenRequest(realm, username, password, null, clientId, clientSecret); return doGrantAccessTokenRequest(realm, username, password, null, clientId, clientSecret);
} }
public AccessTokenResponse doGrantAccessTokenRequest(String clientSecret, String username, String password, String otp) throws Exception {
return doGrantAccessTokenRequest(realm, username, password, otp, clientId, clientSecret);
}
public AccessTokenResponse doGrantAccessTokenRequest(String realm, String username, String password, String totp, public AccessTokenResponse doGrantAccessTokenRequest(String realm, String username, String password, String totp,
String clientId, String clientSecret) throws Exception { String clientId, String clientSecret) throws Exception {
CloseableHttpClient client = new DefaultHttpClient(); CloseableHttpClient client = new DefaultHttpClient();

View file

@ -29,8 +29,10 @@ import org.keycloak.events.Details;
import org.keycloak.events.Errors; import org.keycloak.events.Errors;
import org.keycloak.models.*; import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.TimeBasedOTP;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.representations.RefreshToken; import org.keycloak.representations.RefreshToken;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.OAuthClient; import org.keycloak.testsuite.OAuthClient;
@ -63,9 +65,24 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
user.setEmail("direct-login@localhost"); user.setEmail("direct-login@localhost");
user.setEnabled(true); user.setEnabled(true);
session.users().updateCredential(appRealm, user, UserCredentialModel.password("password"));
userId = user.getId(); userId = user.getId();
session.users().updateCredential(appRealm, user, UserCredentialModel.password("password")); UserModel user2 = session.users().addUser(appRealm, "direct-login-otp");
user2.setEnabled(true);
UserCredentialModel credentials = new UserCredentialModel();
credentials.setType(CredentialRepresentation.TOTP);
credentials.setValue("totpSecret");
user2.updateCredential(credentials);
user2.setOtpEnabled(true);
session.users().updateCredential(appRealm, user2, UserCredentialModel.password("password"));
userId2 = user2.getId();
} }
}); });
@ -83,6 +100,10 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
private static String userId; private static String userId;
private static String userId2;
private TimeBasedOTP totp = new TimeBasedOTP();
@Test @Test
public void grantAccessTokenUsername() throws Exception { public void grantAccessTokenUsername() throws Exception {
grantAccessToken("direct-login", "resource-owner"); grantAccessToken("direct-login", "resource-owner");
@ -98,11 +119,57 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
grantAccessToken("direct-login", "resource-owner-public"); grantAccessToken("direct-login", "resource-owner-public");
} }
@Test
public void grantAccessTokenWithTotp() throws Exception {
grantAccessToken(userId2, "direct-login-otp", "resource-owner", totp.generateTOTP("totpSecret"));
}
@Test
public void grantAccessTokenMissingTotp() throws Exception {
oauth.clientId("resource-owner");
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "direct-login-otp", "password");
assertEquals(401, response.getStatusCode());
assertEquals("invalid_grant", response.getError());
events.expectLogin()
.client("resource-owner")
.session((String) null)
.clearDetails()
.error(Errors.INVALID_USER_CREDENTIALS)
.user(userId2)
.assertEvent();
}
@Test
public void grantAccessTokenInvalidTotp() throws Exception {
oauth.clientId("resource-owner");
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "direct-login-otp", "password", totp.generateTOTP("totpSecret2"));
assertEquals(401, response.getStatusCode());
assertEquals("invalid_grant", response.getError());
events.expectLogin()
.client("resource-owner")
.session((String) null)
.clearDetails()
.error(Errors.INVALID_USER_CREDENTIALS)
.user(userId2)
.assertEvent();
}
private void grantAccessToken(String login, String clientId) throws Exception { private void grantAccessToken(String login, String clientId) throws Exception {
grantAccessToken(userId, login, clientId, null);
}
private void grantAccessToken(String userId, String login, String clientId, String otp) throws Exception {
oauth.clientId(clientId); oauth.clientId(clientId);
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", login, "password"); OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", login, "password", otp);
assertEquals(200, response.getStatusCode()); assertEquals(200, response.getStatusCode());