expanded token service coverage

This commit is contained in:
Bill Burke 2014-08-14 21:01:05 -04:00
parent f7a7c3ca7b
commit 5dca2a3588
3 changed files with 302 additions and 14 deletions

View file

@ -34,6 +34,7 @@ import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.RefreshToken; import org.keycloak.representations.RefreshToken;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AccessCode; import org.keycloak.services.managers.AccessCode;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus; import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus;
@ -245,11 +246,6 @@ public class TokenService {
ClientModel client = authorizeClient(authorizationHeader, form, audit); ClientModel client = authorizeClient(authorizationHeader, form, audit);
if ( (client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
audit.error(Errors.NOT_ALLOWED);
return createError("not_allowed", "Bearer-only applications are not allowed to invoke grants/access", Response.Status.FORBIDDEN);
}
if (!realm.isEnabled()) { if (!realm.isEnabled()) {
audit.error(Errors.REALM_DISABLED); audit.error(Errors.REALM_DISABLED);
return createError("realm_disabled", "Realm is disabled", Response.Status.UNAUTHORIZED); return createError("realm_disabled", "Realm is disabled", Response.Status.UNAUTHORIZED);
@ -312,6 +308,9 @@ public class TokenService {
@NoCache @NoCache
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response validateAccessToken(@QueryParam("access_token") String tokenString) { public Response validateAccessToken(@QueryParam("access_token") String tokenString) {
if (!checkSsl()) {
return createError("https_required", "HTTPS required", Response.Status.FORBIDDEN);
}
audit.event(EventType.VALIDATE_ACCESS_TOKEN); audit.event(EventType.VALIDATE_ACCESS_TOKEN);
AccessToken token = null; AccessToken token = null;
try { try {
@ -423,7 +422,7 @@ public class TokenService {
final MultivaluedMap<String, String> form) { final MultivaluedMap<String, String> form) {
logger.info("--> refreshAccessToken"); logger.info("--> refreshAccessToken");
if (!checkSsl()) { if (!checkSsl()) {
throw new NotAcceptableException("HTTPS required"); return createError("https_required", "HTTPS required", Response.Status.FORBIDDEN);
} }
audit.event(EventType.REFRESH_TOKEN); audit.event(EventType.REFRESH_TOKEN);
@ -716,7 +715,7 @@ public class TokenService {
logger.debug("accessRequest <---"); logger.debug("accessRequest <---");
if (!checkSsl()) { if (!checkSsl()) {
throw new NotAcceptableException("HTTPS required"); throw new ForbiddenException("HTTPS required");
} }
audit.event(EventType.CODE_TO_TOKEN); audit.event(EventType.CODE_TO_TOKEN);

View file

@ -29,6 +29,10 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.audit.Details; import org.keycloak.audit.Details;
import org.keycloak.audit.Errors; import org.keycloak.audit.Errors;
import org.keycloak.audit.Event; import org.keycloak.audit.Event;
import org.keycloak.enums.SslRequired;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
@ -277,13 +281,7 @@ public class AccessTokenTest {
org.keycloak.representations.AccessTokenResponse tokenResponse = null; org.keycloak.representations.AccessTokenResponse tokenResponse = null;
{ {
String header = BasicAuthHelper.createHeader("test-app", "password"); Response response = executeGrantAccessTokenRequest(grantTarget);
Form form = new Form();
form.param("username", "test-user@localhost")
.param("password", "password");
Response response = grantTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(200, response.getStatus());
tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class); tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
response.close(); response.close();
@ -320,5 +318,209 @@ public class AccessTokenTest {
} }
@Test
public void testGrantAccessToken() throws Exception {
Client client = ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI grantUri = TokenService.grantAccessTokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
{ // test checkSsl
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setSslRequired(SslRequired.ALL);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(403, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setSslRequired(SslRequired.EXTERNAL);
session.getTransaction().commit();
session.close();
}
}
{ // test null username
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("password", "password");
Response response = grantTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
Assert.assertEquals(401, response.getStatus());
response.close();
}
{ // test no password
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("username", "test-user@localhost");
Response response = grantTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
Assert.assertEquals(400, response.getStatus());
response.close();
}
{ // test bearer-only
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
ApplicationModel clientModel = realm.getApplicationByName("test-app");
clientModel.setBearerOnly(true);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(400, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
ApplicationModel clientModel = realm.getApplicationByName("test-app");
clientModel.setBearerOnly(false);
session.getTransaction().commit();
session.close();
}
}
{ // test realm disabled
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setEnabled(false);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(401, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setEnabled(true);
session.getTransaction().commit();
session.close();
}
}
{ // test application disabled
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
ClientModel clientModel = realm.findClient("test-app");
clientModel.setEnabled(false);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(400, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
ClientModel clientModel = realm.findClient("test-app");
clientModel.setEnabled(true);
session.getTransaction().commit();
session.close();
}
}
{ // test user action required
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(400, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
user.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
session.getTransaction().commit();
session.close();
}
}
{ // test user disabled
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
user.setEnabled(false);
session.getTransaction().commit();
session.close();
}
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(400, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
UserModel user = session.users().getUserByUsername("test-user@localhost", realm);
user.setEnabled(true);
session.getTransaction().commit();
session.close();
}
}
{
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
response.close();
}
client.close();
events.clear();
}
protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) {
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("username", "test-user@localhost")
.param("password", "password");
return grantTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
}
} }

View file

@ -29,8 +29,12 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.audit.Details; import org.keycloak.audit.Details;
import org.keycloak.audit.Errors; import org.keycloak.audit.Errors;
import org.keycloak.audit.Event; import org.keycloak.audit.Event;
import org.keycloak.enums.SslRequired;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.representations.RefreshToken; import org.keycloak.representations.RefreshToken;
@ -335,6 +339,89 @@ public class RefreshTokenTest {
events.clear(); events.clear();
} }
@Test
public void testCheckSsl() throws Exception {
Client client = ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI grantUri = TokenService.grantAccessTokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
URI uri = TokenService.refreshUrl(builder).build("test");
WebTarget refreshTarget = client.target(uri);
String refreshToken = null;
{
Response response = executeGrantAccessTokenRequest(grantTarget);
Assert.assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
refreshToken = tokenResponse.getRefreshToken();
response.close();
}
{
Response response = executeRefreshToken(refreshTarget, refreshToken);
Assert.assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
refreshToken = tokenResponse.getRefreshToken();
response.close();
}
{ // test checkSsl
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setSslRequired(SslRequired.ALL);
session.getTransaction().commit();
session.close();
}
Response response = executeRefreshToken(refreshTarget, refreshToken);
Assert.assertEquals(403, response.getStatus());
response.close();
{
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.setSslRequired(SslRequired.EXTERNAL);
session.getTransaction().commit();
session.close();
}
}
{
Response response = executeRefreshToken(refreshTarget, refreshToken);
Assert.assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
refreshToken = tokenResponse.getRefreshToken();
response.close();
}
client.close();
events.clear();
}
protected Response executeRefreshToken(WebTarget refreshTarget, String refreshToken) {
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("refresh_token", refreshToken);
return refreshTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
}
protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) {
String header = BasicAuthHelper.createHeader("test-app", "password");
Form form = new Form();
form.param("username", "test-user@localhost")
.param("password", "password");
return grantTarget.request()
.header(HttpHeaders.AUTHORIZATION, header)
.post(Entity.form(form));
}
} }