expanded token service coverage
This commit is contained in:
parent
f7a7c3ca7b
commit
5dca2a3588
3 changed files with 302 additions and 14 deletions
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue