Updated authorization services using Nimbus (#650)
Change-Id: Ia188f533230a850c041b624018383e6d7b7e7a99
diff --git a/full/Changes b/full/Changes
index f9b8f74..8518063 100644
--- a/full/Changes
+++ b/full/Changes
@@ -9,6 +9,7 @@
- Fixed conflicting jackson-jarxrs
- Fixed conflicting commons-logging and spring jcl
- Replaced javax.servlet with jakarta.servlet (#648)
+- Updated authorization services using Nimbus (#650)
# version 0.71
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
index b7027c2..590fb9f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
@@ -290,7 +290,7 @@
String eppn = (String) attributes.get(Attributes.EPPN);
if (eppn == null || eppn.isEmpty())
- throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+ throw new KustvaktException(StatusCodes.INVALID_REQUEST);
if (!attributes.containsKey(Attributes.EMAIL) && validator.isValid(eppn, Attributes.EMAIL))
attributes.put(Attributes.EMAIL, eppn);
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java b/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
index 21f3921..63ec65e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
@@ -179,7 +179,7 @@
try {
jwt = SignedJWT.parse(signedContent);
if (!jwt.verify(verifier))
- throw new KustvaktException(StatusCodes.REQUEST_INVALID,
+ throw new KustvaktException(StatusCodes.INVALID_REQUEST,
"token invalid", signedContent);
return jwt.getJWTClaimsSet().getStringClaim("data");
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java b/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
index efe9338..0915bb5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
+++ b/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
@@ -3,6 +3,8 @@
import java.net.URI;
import java.util.Arrays;
+import com.nimbusds.oauth2.sdk.ErrorObject;
+
//import de.ids_mannheim.korap.constant.TokenType;
import lombok.Getter;
import lombok.Setter;
@@ -25,6 +27,7 @@
private boolean isNotification;
// private TokenType authType;
private URI redirectUri;
+ private ErrorObject oauth2Error;
public KustvaktException (int status) {
this.statusCode = status;
@@ -92,6 +95,13 @@
this.statusCode = status;
}
+ public KustvaktException (int status, String message,
+ ErrorObject oauth2Error) {
+ super(message);
+ this.statusCode = status;
+ this.oauth2Error = oauth2Error;
+ this.entity = oauth2Error.toString();
+ }
public KustvaktException (Throwable cause, int status) {
super(cause);
diff --git a/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index c1777a4..8f16809 100644
--- a/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -112,7 +112,7 @@
public static final int STATUS_OK = 1000;
public static final int NOTHING_CHANGED = 1001;
- public static final int REQUEST_INVALID = 1002;
+ public static final int INVALID_REQUEST = 1002;
// public static final int ACCESS_DENIED = 1003;
@@ -144,12 +144,13 @@
public static final int UNSUPPORTED_GRANT_TYPE = 1811;
public static final int UNSUPPORTED_AUTHENTICATION_METHOD = 1812;
+ public static final int UNSUPPORTED_RESPONSE_TYPE = 1813;
- public static final int ID_TOKEN_CLAIM_ERROR = 1813;
- public static final int ID_TOKEN_SIGNING_FAILED = 1814;
- public static final int USER_REAUTHENTICATION_REQUIRED = 1815;
+ public static final int ID_TOKEN_CLAIM_ERROR = 1820;
+ public static final int ID_TOKEN_SIGNING_FAILED = 1821;
+ public static final int USER_REAUTHENTICATION_REQUIRED = 1822;
- public static final int INVALID_REFRESH_TOKEN_EXPIRY = 1816;
+ public static final int INVALID_REFRESH_TOKEN_EXPIRY = 1830;
/**
* 1850 Plugins
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
index a16b78d..684f5b8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
@@ -61,16 +61,7 @@
OAuth2Client client = clientService.authenticateClientId(clientId);
String redirectUriStr = authzRequest.getRedirectURI();
- String verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr);
-
- URI redirectURI;
- try {
- redirectURI = new URI(verifiedRedirectUri);
- }
- catch (URISyntaxException e) {
- throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
- "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
- }
+ URI redirectURI = verifyRedirectUri(client, redirectUriStr);
String scope, code;
try {
@@ -91,7 +82,7 @@
.authorizationResponse(request,
Status.FOUND.getStatusCode())
.setCode(code).setScope(scope)
- .location(verifiedRedirectUri)
+ .location(redirectURI.toString())
.buildQueryMessage();
}
catch (OAuthSystemException e) {
@@ -137,53 +128,4 @@
return e;
}
- public KustvaktException checkRedirectUri (KustvaktException e,
- String clientId, String redirectUri){
- int statusCode = e.getStatusCode();
- if (!clientId.isEmpty()
- && statusCode != StatusCodes.CLIENT_NOT_FOUND
- && statusCode != StatusCodes.AUTHORIZATION_FAILED
- && statusCode != StatusCodes.INVALID_REDIRECT_URI) {
- String registeredUri = null;
- try {
- OAuth2Client client = clientService.retrieveClient(clientId);
- registeredUri = client.getRedirectURI();
- }
- catch (KustvaktException e1) {}
-
- if (redirectUri != null && !redirectUri.isEmpty()) {
- if (registeredUri != null && !registeredUri.isEmpty()
- && !redirectUri.equals(registeredUri)) {
- return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
- "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
- }
- else {
- try {
- e.setRedirectUri(new URI(redirectUri));
- }
- catch (URISyntaxException e1) {
- return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
- "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
- }
- e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
- }
- }
- else if (registeredUri != null && !registeredUri.isEmpty()) {
- try {
- e.setRedirectUri(new URI(registeredUri));
- }
- catch (URISyntaxException e1) {
- return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
- "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
- }
- e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
- }
- else {
- return new KustvaktException(StatusCodes.MISSING_REDIRECT_URI,
- "Missing parameter: redirect URI", OAuth2Error.INVALID_REQUEST);
- }
- }
-
- return e;
- }
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java
index 65e83aa..d23b146 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java
@@ -100,15 +100,7 @@
String clientId = authzRequest.getClientID().getValue();
OAuth2Client client = clientService.authenticateClientId(clientId);
- String verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr);
-
- try {
- redirectUri = new URI(verifiedRedirectUri);
- }
- catch (URISyntaxException e) {
- throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
- "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
- }
+ URI verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr);
try {
ResponseType responseType = authzRequest.getResponseType();
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
index 8da5caa..220a44a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
@@ -1,20 +1,33 @@
package de.ids_mannheim.korap.oauth2.service;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
import org.apache.commons.validator.routines.UrlValidator;
+import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import com.nimbusds.oauth2.sdk.AuthorizationCode;
+import com.nimbusds.oauth2.sdk.AuthorizationErrorResponse;
+import com.nimbusds.oauth2.sdk.AuthorizationRequest;
+import com.nimbusds.oauth2.sdk.AuthorizationSuccessResponse;
+import com.nimbusds.oauth2.sdk.ErrorObject;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.ResponseType;
+import com.nimbusds.oauth2.sdk.id.State;
+
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
import de.ids_mannheim.korap.oauth2.dao.AuthorizationDao;
import de.ids_mannheim.korap.oauth2.entity.AccessScope;
import de.ids_mannheim.korap.oauth2.entity.Authorization;
@@ -34,6 +47,8 @@
public static boolean DEBUG = false;
@Autowired
+ private RandomCodeGenerator codeGenerator;
+ @Autowired
protected OAuth2ClientService clientService;
@Autowired
protected OAuth2ScopeServiceImpl scopeService;
@@ -44,22 +59,80 @@
@Autowired
protected FullConfiguration config;
+
+ public State createAuthorizationState (String state) {
+ State authState = null;
+ if (state!=null && !state.isEmpty())
+ authState = new State(state);
+ return authState;
+ }
+
+ public AuthorizationErrorResponse createAuthorizationError (
+ KustvaktException e, String state) {
+ State authState = createAuthorizationState(state);
+ ErrorObject error = e.getOauth2Error();
+ error = error.setDescription(e.getMessage());
+ AuthorizationErrorResponse errorResponse =
+ new AuthorizationErrorResponse(e.getRedirectUri(),
+ error,authState, null);
+ return errorResponse;
+ }
+
+ public URI requestAuthorizationCode (URI requestURI,
+ String clientId, String redirectUri, String scope,
+ String state, String username,
+ ZonedDateTime authenticationTime) throws KustvaktException {
+
+ URI redirectURI = null;
+ String code;
+ try {
+ OAuth2Client client = clientService.authenticateClientId(clientId);
+ redirectURI = verifyRedirectUri(client, redirectUri);
+ //checkResponseType(authzRequest.getResponseType(), redirectURI);
+ code = codeGenerator.createRandomCode();
+ createAuthorization(username, clientId, redirectUri, scope, code.toString(),
+ authenticationTime, null);
+ return createAuthorizationResponse(requestURI, redirectURI, code, state);
+ }
+ catch (KustvaktException e) {
+ e.setRedirectUri(redirectURI);
+ throw e;
+ }
+ }
- /**
- * Authorization code request does not require client
- * authentication, but only checks if the client id exists.
- *
- * @param username
- * @param clientId
- * @param redirectUri
- * @param scopeSet
- * @param code
- * @param authenticationTime
- * user authentication time
- * @param nonce
- * @return
- * @throws KustvaktException
- */
+ private URI createAuthorizationResponse (URI requestURI, URI redirectURI,
+ String code, String state) throws KustvaktException {
+ AuthorizationRequest authRequest = null;
+ try {
+ authRequest = AuthorizationRequest.parse(requestURI);
+
+ if (authRequest.getResponseType()
+ .equals(new ResponseType(ResponseType.Value.CODE))) {
+
+ State authState = createAuthorizationState(state);
+ AuthorizationSuccessResponse response =
+ new AuthorizationSuccessResponse(redirectURI,
+ new AuthorizationCode(code), null, authState,
+ null);
+ return response.toURI();
+ }
+ else {
+ KustvaktException ke = new KustvaktException(
+ StatusCodes.UNSUPPORTED_RESPONSE_TYPE,
+ "Unsupported response type. Only code is supported.",
+ OAuth2Error.UNSUPPORTED_RESPONSE_TYPE);
+ throw ke;
+ }
+ }
+ catch (ParseException e) {
+ KustvaktException ke =
+ new KustvaktException(StatusCodes.INVALID_REQUEST,
+ e.getMessage(), OAuth2Error.INVALID_REQUEST_URI);
+ throw ke;
+ }
+
+ }
+ @Deprecated
public String createAuthorization (String username, String clientId,
String redirectUri, Set<String> scopeSet, String code,
ZonedDateTime authenticationTime, String nonce)
@@ -75,6 +148,35 @@
scopes, redirectUri, authenticationTime, nonce);
return String.join(" ", scopeSet);
}
+
+ /**
+ * Authorization code request does not require client
+ * authentication, but only checks if the client id exists.
+ *
+ * @param username
+ * @param clientId
+ * @param redirectUri
+ * @param scopeSet
+ * @param code
+ * @param authenticationTime
+ * user authentication time
+ * @param nonce
+ * @throws KustvaktException
+ */
+ public void createAuthorization (String username, String clientId,
+ String redirectUri, String scope, String code,
+ ZonedDateTime authenticationTime, String nonce)
+ throws KustvaktException {
+
+ if (scope == null || scope.isEmpty()) {
+ throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+ "scope is required", OAuth2Error.INVALID_SCOPE);
+ }
+ Set<AccessScope> accessScopes = scopeService.convertToAccessScope(scope);
+
+ authorizationDao.storeAuthorizationCode(clientId, username, code,
+ accessScopes, redirectUri, authenticationTime, nonce);
+ }
@Deprecated
protected void checkResponseType (String responseType)
@@ -110,7 +212,7 @@
* @return a client's redirect URI
* @throws KustvaktException
*/
- public String verifyRedirectUri (OAuth2Client client, String redirectUri)
+ public URI verifyRedirectUri (OAuth2Client client, String redirectUri)
throws KustvaktException {
String registeredUri = client.getRedirectURI();
@@ -133,8 +235,66 @@
"Missing parameter: redirect URI",
OAuth2Error.INVALID_REQUEST);
}
+ URI redirectURI;
+ try {
+ redirectURI = new URI(redirectUri);
+ }
+ catch (URISyntaxException e) {
+ throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+ "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+ }
+
+ return redirectURI;
+ }
+
+ public KustvaktException checkRedirectUri (KustvaktException e,
+ String clientId, String redirectUri){
+ int statusCode = e.getStatusCode();
+ if (clientId!=null && !clientId.isEmpty()
+ && statusCode != StatusCodes.CLIENT_NOT_FOUND
+ && statusCode != StatusCodes.AUTHORIZATION_FAILED
+ && statusCode != StatusCodes.INVALID_REDIRECT_URI) {
+ String registeredUri = null;
+ try {
+ OAuth2Client client = clientService.retrieveClient(clientId);
+ registeredUri = client.getRedirectURI();
+ }
+ catch (KustvaktException e1) {}
- return redirectUri;
+ if (redirectUri != null && !redirectUri.isEmpty()) {
+ if (registeredUri != null && !registeredUri.isEmpty()
+ && !redirectUri.equals(registeredUri)) {
+ return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+ "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+ }
+ else {
+ try {
+ e.setRedirectUri(new URI(redirectUri));
+ }
+ catch (URISyntaxException e1) {
+ return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+ "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+ }
+ e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
+ }
+ }
+ else if (registeredUri != null && !registeredUri.isEmpty()) {
+ try {
+ e.setRedirectUri(new URI(registeredUri));
+ }
+ catch (URISyntaxException e1) {
+ return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+ "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+ }
+ e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
+ }
+ else {
+ return new KustvaktException(StatusCodes.MISSING_REDIRECT_URI,
+ "Missing parameter: redirect URI", OAuth2Error.INVALID_REQUEST);
+ }
+ }
+
+ return e;
}
public Authorization retrieveAuthorization (String code)
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
index ee7aa91..819a839 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
@@ -13,6 +13,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
import de.ids_mannheim.korap.config.FullConfiguration;
import de.ids_mannheim.korap.dao.AdminDao;
import de.ids_mannheim.korap.dto.InstalledPluginDto;
@@ -22,7 +24,6 @@
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.interfaces.EncryptionIface;
import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
import de.ids_mannheim.korap.oauth2.dao.AuthorizationDao;
import de.ids_mannheim.korap.oauth2.dao.InstalledPluginDao;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
index 9102ea3..56f0115 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
@@ -10,13 +10,14 @@
import org.springframework.beans.factory.annotation.Autowired;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.constant.OAuth2Scope;
import de.ids_mannheim.korap.constant.TokenType;
import de.ids_mannheim.korap.dao.AdminDao;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
import de.ids_mannheim.korap.oauth2.dao.AccessScopeDao;
import de.ids_mannheim.korap.oauth2.entity.AccessScope;
import de.ids_mannheim.korap.security.context.TokenContext;
@@ -41,6 +42,7 @@
* @return
* @throws KustvaktException
*/
+ @Deprecated
public Set<AccessScope> convertToAccessScope (Collection<String> scopes)
throws KustvaktException {
@@ -56,14 +58,47 @@
}
catch (IllegalArgumentException e) {
throw new KustvaktException(StatusCodes.INVALID_SCOPE,
- scope + " is an invalid scope",
+ "Invalid scope",
OAuth2Error.INVALID_SCOPE);
}
index = definedScopes.indexOf(new AccessScope(oauth2Scope));
if (index == -1) {
throw new KustvaktException(StatusCodes.INVALID_SCOPE,
- scope + " is an invalid scope",
+ "Invalid scope",
+ OAuth2Error.INVALID_SCOPE);
+ }
+ else {
+ requestedScopes.add(definedScopes.get(index));
+ }
+ }
+ return requestedScopes;
+ }
+
+ public Set<AccessScope> convertToAccessScope (String scopes)
+ throws KustvaktException {
+
+ String[] scopeArray = scopes.split(" ");
+ List<AccessScope> definedScopes = accessScopeDao.retrieveAccessScopes();
+ Set<AccessScope> requestedScopes =
+ new HashSet<AccessScope>(scopeArray.length);
+ int index;
+ OAuth2Scope oauth2Scope = null;
+ for (String scope : scopeArray) {
+ try {
+ oauth2Scope =
+ Enum.valueOf(OAuth2Scope.class, scope.toUpperCase());
+ }
+ catch (IllegalArgumentException e) {
+ throw new KustvaktException(StatusCodes.INVALID_SCOPE,
+ "Invalid scope",
+ OAuth2Error.INVALID_SCOPE);
+ }
+
+ index = definedScopes.indexOf(new AccessScope(oauth2Scope));
+ if (index == -1) {
+ throw new KustvaktException(StatusCodes.INVALID_SCOPE,
+ "Invalid scope",
OAuth2Error.INVALID_SCOPE);
}
else {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
index 2f82719..4964913 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
@@ -34,7 +34,7 @@
return service.path(path).queryParam(key, value).request().get(String.class);
}
catch (WebApplicationException e) {
- throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+ throw new KustvaktException(StatusCodes.INVALID_REQUEST);
}
}
@@ -52,7 +52,7 @@
return resource.request().get(String.class);
}
catch (WebApplicationException e) {
- throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+ throw new KustvaktException(StatusCodes.INVALID_REQUEST);
}
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
index cd9fb9c..077383f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
@@ -4,15 +4,15 @@
import java.net.URISyntaxException;
import org.apache.http.HttpHeaders;
-import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.OAuthResponse.OAuthErrorResponseBuilder;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@@ -80,6 +80,7 @@
public WebApplicationException throwit (KustvaktException e, String state) {
String errorCode = e.getEntity();
+
int responseStatus = e.getResponseStatus();
try {
if(responseStatus>0) {
@@ -88,30 +89,30 @@
else if (errorCode == null){
return super.throwit(e);
}
- else if (errorCode.equals(OAuth2Error.INVALID_CLIENT)
- || errorCode.equals(OAuth2Error.UNAUTHORIZED_CLIENT)
- || errorCode.equals(OAuth2Error.INVALID_TOKEN)) {
+ else if (errorCode.equals(OAuth2Error.INVALID_CLIENT.getCode())
+ || errorCode.equals(OAuth2Error.UNAUTHORIZED_CLIENT.getCode())
+ || errorCode.equals(de.ids_mannheim.korap.oauth2.constant.OAuth2Error.INVALID_TOKEN)) {
return throwit(createOAuthProblemException(e,
Status.UNAUTHORIZED.getStatusCode(), state));
}
- else if (errorCode.equals(OAuth2Error.INVALID_GRANT)
- || errorCode.equals(OAuth2Error.INVALID_REQUEST)
- || errorCode.equals(OAuth2Error.INVALID_SCOPE)
- || errorCode.equals(OAuth2Error.UNSUPPORTED_GRANT_TYPE)
- || errorCode.equals(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE)
- || errorCode.equals(OAuth2Error.ACCESS_DENIED)) {
+ else if (errorCode.equals(OAuth2Error.INVALID_GRANT.getCode())
+ || errorCode.equals(OAuth2Error.INVALID_REQUEST.getCode())
+ || errorCode.equals(OAuth2Error.INVALID_SCOPE.getCode())
+ || errorCode.equals(OAuth2Error.UNSUPPORTED_GRANT_TYPE.getCode())
+ || errorCode.equals(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE.getCode())
+ || errorCode.equals(OAuth2Error.ACCESS_DENIED.getCode())) {
return throwit(createOAuthProblemException(e,
Status.BAD_REQUEST.getStatusCode(), state));
}
- else if (errorCode.equals(OAuth2Error.INSUFFICIENT_SCOPE)) {
+ else if (errorCode.equals(de.ids_mannheim.korap.oauth2.constant.OAuth2Error.INSUFFICIENT_SCOPE)) {
return throwit(createOAuthProblemException(e,
Status.FORBIDDEN.getStatusCode(), state));
}
- else if (errorCode.equals(OAuth2Error.SERVER_ERROR)) {
+ else if (errorCode.equals(OAuth2Error.SERVER_ERROR.getCode())) {
return throwit(createOAuthProblemException(e,
Status.INTERNAL_SERVER_ERROR.getStatusCode(), state));
}
- else if (errorCode.equals(OAuth2Error.TEMPORARILY_UNAVAILABLE)) {
+ else if (errorCode.equals(OAuth2Error.TEMPORARILY_UNAVAILABLE.getCode())) {
return throwit(createOAuthProblemException(e,
Status.SERVICE_UNAVAILABLE.getStatusCode(), state));
}
@@ -181,15 +182,8 @@
return builder.build();
}
- public Response sendRedirect (String locationUri) throws KustvaktException {
- try {
- ResponseBuilder builder =
- Response.temporaryRedirect(new URI(locationUri));
- return builder.build();
- }
- catch (URISyntaxException e) {
- throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
- e.getMessage(), OAuthError.CodeResponse.INVALID_REQUEST);
- }
+ public Response sendRedirect (URI locationUri) {
+ ResponseBuilder builder = Response.temporaryRedirect(locationUri);
+ return builder.build();
}
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
index c380aab..a777131 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
@@ -366,7 +366,7 @@
authorizationData.getPassword()== null ||
authorizationData.getPassword().isEmpty())
// is actual an invalid request
- throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
+ throw kustvaktResponseHandler.throwit(StatusCodes.INVALID_REQUEST);
Map<String, Object> attr = new HashMap<>();
attr.put(Attributes.HOST, host);
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
index ecbe9c8..422aae0 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
@@ -1,49 +1,33 @@
package de.ids_mannheim.korap.web.controller;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.time.ZonedDateTime;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.oltu.oauth2.as.request.AbstractOAuthTokenRequest;
-import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
-import org.apache.oltu.oauth2.as.request.OAuthUnauthenticatedTokenRequest;
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
-import org.apache.oltu.oauth2.common.message.OAuthResponse;
-import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
+import com.nimbusds.oauth2.sdk.AuthorizationErrorResponse;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+import com.nimbusds.oauth2.sdk.id.State;
+
import de.ids_mannheim.korap.constant.OAuth2Scope;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.oauth2.dto.OAuth2TokenDto;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2AuthorizationRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeAllTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.oltu.service.OltuAuthorizationService;
-import de.ids_mannheim.korap.oauth2.oltu.service.OltuTokenService;
+import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService;
import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
import de.ids_mannheim.korap.security.context.TokenContext;
import de.ids_mannheim.korap.web.OAuth2ResponseHandler;
import de.ids_mannheim.korap.web.filter.APIVersionFilter;
import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
-import de.ids_mannheim.korap.web.filter.BlockingFilter;
-import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
import de.ids_mannheim.korap.web.utils.ResourceFilters;
-import jakarta.ws.rs.Consumes;
-import jakarta.ws.rs.FormParam;
+import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.GET;
-import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
@@ -60,16 +44,23 @@
*/
@Controller
@Path("{version}/oauth2")
-@ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class, BlockingFilter.class })
+@ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class
+ //, BlockingFilter.class
+ })
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public class OAuth2Controller {
@Autowired
private OAuth2ResponseHandler responseHandler;
+// @Autowired
+// private OltuTokenService tokenService;
+// @Deprecated
+// @Autowired
+// private OltuAuthorizationService authorizationService;
+
@Autowired
- private OltuTokenService tokenService;
- @Autowired
- private OltuAuthorizationService authorizationService;
+ private OAuth2AuthorizationService authorizationService;
+
@Autowired
private OAuth2ScopeService scopeService;
@@ -94,81 +85,90 @@
* form parameters
* @return a redirect URL
*/
- @Deprecated
- @POST
- @Path("authorize")
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response requestAuthorizationCode (
- @Context HttpServletRequest request,
- @Context SecurityContext context,
- @FormParam("state") String state,
- @FormParam("client_id") String clientId,
- @FormParam("redirect_uri") String redirectUri,
- MultivaluedMap<String, String> form) {
-
- TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
- String username = tokenContext.getUsername();
- ZonedDateTime authTime = tokenContext.getAuthenticationTime();
-
- try {
- scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
-
- HttpServletRequest requestWithForm =
- new FormRequestWrapper(request, form);
- OAuth2AuthorizationRequest authzRequest =
- new OAuth2AuthorizationRequest(requestWithForm);
- String uri = authorizationService.requestAuthorizationCode(
- requestWithForm, authzRequest, username, authTime);
- return responseHandler.sendRedirect(uri);
- }
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e, state);
- }
- catch (OAuthProblemException e) {
- e.state(state);
- e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
- throw responseHandler.throwit(e);
- }
- catch (KustvaktException e) {
- e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
- throw responseHandler.throwit(e, state);
- }
- }
+// @Deprecated
+// @POST
+// @Path("authorize")
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public Response requestAuthorizationCode (
+// @Context HttpServletRequest request,
+// @Context SecurityContext context,
+// @FormParam("state") String state,
+// @FormParam("client_id") String clientId,
+// @FormParam("redirect_uri") String redirectUri,
+// MultivaluedMap<String, String> form) {
+//
+// TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+// String username = tokenContext.getUsername();
+// ZonedDateTime authTime = tokenContext.getAuthenticationTime();
+//
+// try {
+// scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
+//
+// HttpServletRequest requestWithForm =
+// new FormRequestWrapper(request, form);
+// OAuth2AuthorizationRequest authzRequest =
+// new OAuth2AuthorizationRequest(requestWithForm);
+// String uri = authorizationService.requestAuthorizationCode(
+// requestWithForm, authzRequest, username, authTime);
+// return responseHandler.sendRedirect(uri);
+// }
+// catch (OAuthSystemException e) {
+// throw responseHandler.throwit(e, state);
+// }
+// catch (OAuthProblemException e) {
+// e.state(state);
+// e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
+// throw responseHandler.throwit(e);
+// }
+// catch (KustvaktException e) {
+// e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
+// throw responseHandler.throwit(e, state);
+// }
+// }
@GET
@Path("authorize")
public Response requestAuthorizationCode (
@Context HttpServletRequest request,
@Context SecurityContext context,
+ @QueryParam("response_type") String responseType,
@QueryParam("client_id") String clientId,
@QueryParam("redirect_uri") String redirectUri,
- @QueryParam("state") String state
- ) {
+ @QueryParam("scope") String scope,
+ @QueryParam("state") String state) {
TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
String username = tokenContext.getUsername();
ZonedDateTime authTime = tokenContext.getAuthenticationTime();
+ URI requestURI;
+ try {
+ requestURI = new URI(request.getRequestURI()+"?"+request.getQueryString());
+ }
+ catch (URISyntaxException e) {
+ KustvaktException ke = new KustvaktException(
+ StatusCodes.INVALID_REQUEST, "Failed parsing request URI.",
+ OAuth2Error.INVALID_REQUEST_URI);
+ throw responseHandler.throwit(ke, state);
+ }
+
try {
scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
-
- OAuth2AuthorizationRequest authzRequest =
- new OAuth2AuthorizationRequest(request);
- String uri = authorizationService.requestAuthorizationCode(
- request, authzRequest, username, authTime);
+ URI uri = authorizationService.requestAuthorizationCode(
+ requestURI, clientId, redirectUri,
+ scope, state, username, authTime);
return responseHandler.sendRedirect(uri);
}
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e,state);
- }
- catch (OAuthProblemException e) {
- e.state(state);
- e = authorizationService.checkRedirectUri(e,clientId,redirectUri);
- throw responseHandler.throwit(e);
- }
catch (KustvaktException e) {
e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
- throw responseHandler.throwit(e,state);
+ if (e.getRedirectUri() != null) {
+ AuthorizationErrorResponse errorResponse =
+ authorizationService.createAuthorizationError(e, state);
+ return responseHandler.sendRedirect(errorResponse.toURI());
+ }
+ else {
+ throw responseHandler.throwit(e, state);
+ }
}
}
@@ -234,42 +234,42 @@
* if successful, an error code and an error description
* otherwise.
*/
- @POST
- @Path("token")
- @ResourceFilters({APIVersionFilter.class})
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response requestAccessToken (@Context HttpServletRequest request,
- @FormParam("grant_type") String grantType,
- MultivaluedMap<String, String> form) {
-
- try {
- boolean grantTypeExist = grantType != null && !grantType.isEmpty();
- AbstractOAuthTokenRequest oAuthRequest = null;
- if (grantTypeExist && grantType
- .equals(GrantType.CLIENT_CREDENTIALS.toString())) {
- oAuthRequest = new OAuthTokenRequest(
- new FormRequestWrapper(request, form));
- }
- else {
- oAuthRequest = new OAuthUnauthenticatedTokenRequest(
- new FormRequestWrapper(request, form));
- }
-
- OAuthResponse oAuthResponse =
- tokenService.requestAccessToken(oAuthRequest);
-
- return responseHandler.createResponse(oAuthResponse);
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
- catch (OAuthProblemException e) {
- throw responseHandler.throwit(e);
- }
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e);
- }
- }
+// @POST
+// @Path("token")
+// @ResourceFilters({APIVersionFilter.class})
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public Response requestAccessToken (@Context HttpServletRequest request,
+// @FormParam("grant_type") String grantType,
+// MultivaluedMap<String, String> form) {
+//
+// try {
+// boolean grantTypeExist = grantType != null && !grantType.isEmpty();
+// AbstractOAuthTokenRequest oAuthRequest = null;
+// if (grantTypeExist && grantType
+// .equals(GrantType.CLIENT_CREDENTIALS.toString())) {
+// oAuthRequest = new OAuthTokenRequest(
+// new FormRequestWrapper(request, form));
+// }
+// else {
+// oAuthRequest = new OAuthUnauthenticatedTokenRequest(
+// new FormRequestWrapper(request, form));
+// }
+//
+// OAuthResponse oAuthResponse =
+// tokenService.requestAccessToken(oAuthRequest);
+//
+// return responseHandler.createResponse(oAuthResponse);
+// }
+// catch (KustvaktException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (OAuthProblemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (OAuthSystemException e) {
+// throw responseHandler.throwit(e);
+// }
+// }
/**
* Revokes either an access token or a refresh token. Revoking a
@@ -289,59 +289,59 @@
* @return 200 if token invalidation is successful or the given
* token is invalid
*/
- @POST
- @Path("revoke")
- @ResourceFilters({APIVersionFilter.class})
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response revokeAccessToken (@Context HttpServletRequest request,
- MultivaluedMap<String, String> form) {
-
- try {
- OAuth2RevokeTokenRequest revokeTokenRequest =
- new OAuth2RevokeTokenRequest(
- new FormRequestWrapper(request, form));
- tokenService.revokeToken(revokeTokenRequest);
- return Response.ok("SUCCESS").build();
- }
- catch (OAuthProblemException e) {
- throw responseHandler.throwit(e);
- }
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e);
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
- }
-
- @POST
- @Path("revoke/super")
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response revokeTokenViaSuperClient (@Context SecurityContext context,
- @Context HttpServletRequest request,
- MultivaluedMap<String, String> form) {
-
- TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
- String username = tokenContext.getUsername();
-
- try {
- OAuth2RevokeTokenSuperRequest revokeTokenRequest =
- new OAuth2RevokeTokenSuperRequest(
- new FormRequestWrapper(request, form));
- tokenService.revokeTokensViaSuperClient(username,
- revokeTokenRequest);
- return Response.ok("SUCCESS").build();
- }
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e);
- }
- catch (OAuthProblemException e) {
- throw responseHandler.throwit(e);
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
- }
+// @POST
+// @Path("revoke")
+// @ResourceFilters({APIVersionFilter.class})
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public Response revokeAccessToken (@Context HttpServletRequest request,
+// MultivaluedMap<String, String> form) {
+//
+// try {
+// OAuth2RevokeTokenRequest revokeTokenRequest =
+// new OAuth2RevokeTokenRequest(
+// new FormRequestWrapper(request, form));
+// tokenService.revokeToken(revokeTokenRequest);
+// return Response.ok("SUCCESS").build();
+// }
+// catch (OAuthProblemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (OAuthSystemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (KustvaktException e) {
+// throw responseHandler.throwit(e);
+// }
+// }
+//
+// @POST
+// @Path("revoke/super")
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public Response revokeTokenViaSuperClient (@Context SecurityContext context,
+// @Context HttpServletRequest request,
+// MultivaluedMap<String, String> form) {
+//
+// TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+// String username = tokenContext.getUsername();
+//
+// try {
+// OAuth2RevokeTokenSuperRequest revokeTokenRequest =
+// new OAuth2RevokeTokenSuperRequest(
+// new FormRequestWrapper(request, form));
+// tokenService.revokeTokensViaSuperClient(username,
+// revokeTokenRequest);
+// return Response.ok("SUCCESS").build();
+// }
+// catch (OAuthSystemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (OAuthProblemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (KustvaktException e) {
+// throw responseHandler.throwit(e);
+// }
+// }
/**
* Revokes all tokens of a client for the authenticated user from
@@ -357,67 +357,67 @@
* @return 200 if token invalidation is successful or the given
* token is invalid
*/
- @POST
- @Path("revoke/super/all")
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public Response revokeAllClientTokensViaSuperClient (
- @Context SecurityContext context,
- @Context HttpServletRequest request,
- MultivaluedMap<String, String> form) {
-
- TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
- String username = tokenContext.getUsername();
-
- try {
- OAuth2RevokeAllTokenSuperRequest revokeTokenRequest =
- new OAuth2RevokeAllTokenSuperRequest(
- new FormRequestWrapper(request, form));
- tokenService.revokeAllClientTokensViaSuperClient(username,
- revokeTokenRequest);
- return Response.ok("SUCCESS").build();
- }
- catch (OAuthSystemException e) {
- throw responseHandler.throwit(e);
- }
- catch (OAuthProblemException e) {
- throw responseHandler.throwit(e);
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
- }
-
- @POST
- @Path("token/list")
- @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
- public List<OAuth2TokenDto> listUserToken (
- @Context SecurityContext context,
- @FormParam("super_client_id") String superClientId,
- @FormParam("super_client_secret") String superClientSecret,
- @FormParam("client_id") String clientId, // optional
- @FormParam("token_type") String tokenType) {
-
- TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
- String username = tokenContext.getUsername();
-
- try {
- if (tokenType.equals("access_token")) {
- return tokenService.listUserAccessToken(username, superClientId,
- superClientSecret, clientId);
- }
- else if (tokenType.equals("refresh_token")) {
- return tokenService.listUserRefreshToken(username,
- superClientId, superClientSecret, clientId);
- }
- else {
- throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
- "Missing token_type parameter value",
- OAuth2Error.INVALID_REQUEST);
- }
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
-
- }
+// @POST
+// @Path("revoke/super/all")
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public Response revokeAllClientTokensViaSuperClient (
+// @Context SecurityContext context,
+// @Context HttpServletRequest request,
+// MultivaluedMap<String, String> form) {
+//
+// TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+// String username = tokenContext.getUsername();
+//
+// try {
+// OAuth2RevokeAllTokenSuperRequest revokeTokenRequest =
+// new OAuth2RevokeAllTokenSuperRequest(
+// new FormRequestWrapper(request, form));
+// tokenService.revokeAllClientTokensViaSuperClient(username,
+// revokeTokenRequest);
+// return Response.ok("SUCCESS").build();
+// }
+// catch (OAuthSystemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (OAuthProblemException e) {
+// throw responseHandler.throwit(e);
+// }
+// catch (KustvaktException e) {
+// throw responseHandler.throwit(e);
+// }
+// }
+//
+// @POST
+// @Path("token/list")
+// @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+// public List<OAuth2TokenDto> listUserToken (
+// @Context SecurityContext context,
+// @FormParam("super_client_id") String superClientId,
+// @FormParam("super_client_secret") String superClientSecret,
+// @FormParam("client_id") String clientId, // optional
+// @FormParam("token_type") String tokenType) {
+//
+// TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+// String username = tokenContext.getUsername();
+//
+// try {
+// if (tokenType.equals("access_token")) {
+// return tokenService.listUserAccessToken(username, superClientId,
+// superClientSecret, clientId);
+// }
+// else if (tokenType.equals("refresh_token")) {
+// return tokenService.listUserRefreshToken(username,
+// superClientId, superClientSecret, clientId);
+// }
+// else {
+// throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+// "Missing token_type parameter value",
+// OAuth2Error.INVALID_REQUEST);
+// }
+// }
+// catch (KustvaktException e) {
+// throw responseHandler.throwit(e);
+// }
+//
+// }
}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java
new file mode 100644
index 0000000..3019784
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java
@@ -0,0 +1,287 @@
+package de.ids_mannheim.korap.web.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.apache.oltu.oauth2.common.error.OAuthError;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+
+public class OAuth2AuthorizationTest extends OAuth2TestBase {
+
+ private String userAuthHeader;
+
+ public OAuth2AuthorizationTest () throws KustvaktException {
+ userAuthHeader = HttpAuthorizationHandler
+ .createBasicAuthorizationHeaderValue("dory", "password");
+ }
+
+ @Test
+ public void testAuthorizeConfidentialClient () throws KustvaktException {
+ // with registered redirect URI
+ Response response =
+ requestAuthorizationCode("code", confidentialClientId, "",
+ "match_info search client_info", state, userAuthHeader);
+
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+ URI redirectUri = response.getLocation();
+ MultivaluedMap<String, String> params =
+ getQueryParamsFromURI(redirectUri);
+ assertNotNull(params.getFirst("code"));
+ assertEquals(state, params.getFirst("state"));
+ }
+
+ @Test
+ public void testAuthorizePublicClient () throws KustvaktException {
+ // with registered redirect URI
+ String code = requestAuthorizationCode(publicClientId, userAuthHeader);
+ assertNotNull(code);
+ }
+
+ @Test
+ public void testAuthorizeWithRedirectUri () throws KustvaktException {
+ Response response =
+ requestAuthorizationCode("code", publicClientId2,
+ "https://public.com/redirect", "search match_info",
+ "", userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ URI redirectUri = response.getLocation();
+ assertEquals("https", redirectUri.getScheme());
+ assertEquals("public.com", redirectUri.getHost());
+ assertEquals("/redirect", redirectUri.getPath());
+
+ assertTrue(redirectUri.getQuery().startsWith("code="));
+ }
+
+ @Test
+ public void testAuthorizeWithoutScope () throws KustvaktException {
+ Response response = requestAuthorizationCode("code",
+ confidentialClientId, "", "", "", userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ URI redirectUri = response.getLocation();
+ assertEquals(redirectUri.getScheme(), "https");
+ assertEquals(redirectUri.getHost(), "third.party.com");
+ assertEquals(redirectUri.getPath(), "/confidential/redirect");
+
+ String[] queryParts = redirectUri.getQuery().split("&");
+ assertEquals("error_description=scope+is+required",
+ queryParts[1]);
+ assertEquals("error=invalid_scope", queryParts[0]);
+ }
+
+ @Test
+ public void testAuthorizeMissingClientId () throws KustvaktException {
+ Response response = requestAuthorizationCode("code", "", "", "search",
+ "", userAuthHeader);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals("Missing parameter: client_id",
+ node.at("/error_description").asText());
+ }
+
+ @Test
+ public void testAuthorizeMissingRedirectUri () throws KustvaktException {
+ Response response = requestAuthorizationCode("code",
+ publicClientId2, "", "search", state, userAuthHeader);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+ node.at("/error").asText());
+ assertEquals("Missing parameter: redirect URI",
+ node.at("/error_description").asText());
+ assertEquals(state, node.at("/state").asText());
+ }
+
+ @Test
+ public void testAuthorizeMissingResponseType() throws KustvaktException {
+ Response response = requestAuthorizationCode("",
+ confidentialClientId, "", "search", "", userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ assertEquals("https://third.party.com/confidential/redirect?"
+ + "error=invalid_request_uri&"
+ + "error_description=Missing+response_type+parameter"
+ , response.getLocation().toString());
+ }
+
+ @Test
+ public void testAuthorizeMissingResponseTypeWithoutClientId () throws KustvaktException {
+ Response response = requestAuthorizationCode("",
+ "", "", "search", "", userAuthHeader);
+
+ assertEquals(Status.BAD_REQUEST.getStatusCode(),
+ response.getStatus());
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+
+ assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+ node.at("/error").asText());
+ assertEquals("Missing parameter: client_id",
+ node.at("/error_description").asText());
+ }
+
+ @Test
+ public void testAuthorizeInvalidClientId () throws KustvaktException {
+ Response response = requestAuthorizationCode("code",
+ "unknown-client-id", "", "search", "", userAuthHeader);
+ assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(OAuth2Error.INVALID_CLIENT, node.at("/error").asText());
+ assertEquals("Unknown client: unknown-client-id",
+ node.at("/error_description").asText());
+ }
+
+ @Test
+ public void testAuthorizeDifferentRedirectUri () throws KustvaktException {
+ String redirectUri = "https://different.uri/redirect";
+ Response response = requestAuthorizationCode("code",
+ confidentialClientId, redirectUri, "", state, userAuthHeader);
+
+ testInvalidRedirectUri(response.readEntity(String.class),
+ response.getHeaderString("Content-Type"),true,
+ response.getStatus());
+ }
+
+ @Test
+ public void testAuthorizeWithRedirectUriLocalhost ()
+ throws KustvaktException {
+ Response response = requestAuthorizationCode("code", publicClientId2,
+ "http://localhost:1410", "search", state, userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ URI redirectUri = response.getLocation();
+ MultivaluedMap<String, String> params =
+ getQueryParamsFromURI(redirectUri);
+ assertNotNull(params.getFirst("code"));
+ assertEquals(state, params.getFirst("state"));
+ }
+
+ @Test
+ public void testAuthorizeWithRedirectUriFragment ()
+ throws KustvaktException {
+ Response response = requestAuthorizationCode("code",
+ publicClientId2, "http://public.com/index.html#redirect", "search",
+ state, userAuthHeader);
+ testInvalidRedirectUri(response.readEntity(String.class),
+ response.getHeaderString("Content-Type"),true,
+ response.getStatus());
+ }
+
+ @Test
+ public void testAuthorizeInvalidRedirectUri () throws KustvaktException {
+ // host not allowed by Apache URI Validator
+ String redirectUri = "https://public.uri/redirect";
+ Response response = requestAuthorizationCode("code",
+ publicClientId2, redirectUri, "", state, userAuthHeader);
+ testInvalidRedirectUri(response.readEntity(String.class),
+ response.getHeaderString("Content-Type"),true,
+ response.getStatus());
+ }
+
+ @Test
+ public void testAuthorizeInvalidResponseType () throws KustvaktException {
+ // without redirect URI in the request
+ Response response = requestAuthorizationCode("string",
+ confidentialClientId, "", "search", state, userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ assertEquals("https://third.party.com/confidential/redirect?"
+ + "error=unsupported_response_type"
+ + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+ + "&state=thisIsMyState" ,
+ response.getLocation().toString());
+
+ // with redirect URI, and no registered redirect URI
+ response = requestAuthorizationCode("string", publicClientId2,
+ "https://public.client.com/redirect", "search", state,
+ userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ assertEquals("https://public.client.com/redirect?"
+ + "error=unsupported_response_type"
+ + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+ + "&state=thisIsMyState",
+ response.getLocation().toString());
+
+ // with different redirect URI
+ String redirectUri = "https://different.uri/redirect";
+ response = requestAuthorizationCode("string", confidentialClientId,
+ redirectUri, "", state, userAuthHeader);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
+ assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+ node.at("/error").asText());
+ assertEquals("Invalid redirect URI",
+ node.at("/error_description").asText());
+ assertEquals(state, node.at("/state").asText());
+
+ // without redirect URI in the request and no registered
+ // redirect URI
+ response = requestAuthorizationCode("string", publicClientId2, "", "",
+ state, userAuthHeader);
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ node = JsonUtils.readTree(response.readEntity(String.class));
+ assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+ node.at("/error").asText());
+ assertEquals("Missing parameter: redirect URI",
+ node.at("/error_description").asText());
+ assertEquals(state, node.at("/state").asText());
+ }
+
+ @Test
+ public void testAuthorizeInvalidScope () throws KustvaktException {
+ String scope = "read_address";
+ Response response = requestAuthorizationCode("code",
+ confidentialClientId, "", scope, state, userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ assertEquals(
+ "https://third.party.com/confidential/redirect?"
+ + "error=invalid_scope&error_description=Invalid+"
+ +"scope&state=thisIsMyState",
+ response.getLocation().toString());
+ }
+
+ @Test
+ public void testAuthorizeUnsupportedTokenResponseType ()
+ throws KustvaktException {
+ Response response = requestAuthorizationCode("token",
+ confidentialClientId, "", "search", state, userAuthHeader);
+ assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+ response.getStatus());
+
+ assertEquals("https://third.party.com/confidential/redirect?"
+ + "error=unsupported_response_type"
+ + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+ + "&state=thisIsMyState", response.getLocation().toString());
+ }
+
+}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
index e34586a..bb5440c 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
@@ -8,7 +8,6 @@
import java.net.URI;
import org.apache.http.entity.ContentType;
-import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
@@ -19,6 +18,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.net.HttpHeaders;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
import de.ids_mannheim.korap.config.Attributes;
@@ -26,7 +26,6 @@
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
import de.ids_mannheim.korap.utils.JsonUtils;
import de.ids_mannheim.korap.utils.TimeUtils;
@@ -35,6 +34,7 @@
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation.Builder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Form;
import jakarta.ws.rs.core.MultivaluedMap;
@@ -119,8 +119,9 @@
request = request.queryParam("state", state);
}
- return request.request().header(Attributes.AUTHORIZATION, authHeader)
- .get();
+ Builder builder = request.request().header(Attributes.AUTHORIZATION, authHeader);
+
+ return builder.get();
}
protected String requestAuthorizationCode (String clientId,
@@ -449,7 +450,7 @@
protected void testInvalidRedirectUri (String entity, String contentType,
boolean includeState, int status) throws KustvaktException {
JsonNode node = JsonUtils.readTree(entity);
- assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+ assertEquals(OAuth2Error.INVALID_REQUEST.getCode(),
node.at("/error").asText());
assertEquals("Invalid redirect URI",
node.at("/error_description").asText());