| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 1 | package de.ids_mannheim.korap.oauth2.oltu.service; |
| 2 | |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 3 | import java.net.URI; |
| 4 | import java.net.URISyntaxException; |
| margaretha | a2ce63d | 2018-06-28 10:11:43 +0200 | [diff] [blame] | 5 | import java.time.ZonedDateTime; |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 6 | |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 7 | import javax.servlet.http.HttpServletRequest; |
| 8 | |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 9 | import org.apache.http.HttpStatus; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 10 | import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; |
| 11 | import org.apache.oltu.oauth2.as.response.OAuthASResponse; |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 12 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 13 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; |
| 14 | import org.apache.oltu.oauth2.common.message.OAuthResponse; |
| 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 16 | import org.springframework.stereotype.Service; |
| 17 | |
| 18 | import com.sun.jersey.api.client.ClientResponse.Status; |
| 19 | |
| margaretha | 33fa3d9 | 2018-07-26 13:50:17 +0200 | [diff] [blame] | 20 | import de.ids_mannheim.korap.encryption.RandomCodeGenerator; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 21 | import de.ids_mannheim.korap.exceptions.KustvaktException; |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 22 | import de.ids_mannheim.korap.exceptions.StatusCodes; |
| 23 | import de.ids_mannheim.korap.oauth2.constant.OAuth2Error; |
| margaretha | da3c785 | 2018-06-14 20:35:11 +0200 | [diff] [blame] | 24 | import de.ids_mannheim.korap.oauth2.entity.OAuth2Client; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 25 | import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService; |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 26 | import de.ids_mannheim.korap.oauth2.service.OAuth2ClientService; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 27 | |
| 28 | /** |
| 29 | * OAuth2 authorization service using Apache Oltu |
| 30 | * |
| 31 | * @author margaretha |
| 32 | * |
| 33 | */ |
| 34 | @Service |
| 35 | public class OltuAuthorizationService extends OAuth2AuthorizationService { |
| 36 | |
| 37 | @Autowired |
| margaretha | 33fa3d9 | 2018-07-26 13:50:17 +0200 | [diff] [blame] | 38 | private RandomCodeGenerator codeGenerator; |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 39 | @Autowired |
| 40 | private OAuth2ClientService clientService; |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 41 | |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 42 | /**e.description("Redirect URI is required"); |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 43 | * Authorization code request does not require client |
| 44 | * authentication, but only checks if the client id exists. |
| 45 | * |
| 46 | * @param request |
| 47 | * @param authzRequest |
| 48 | * @param username |
| margaretha | a2ce63d | 2018-06-28 10:11:43 +0200 | [diff] [blame] | 49 | * @param authTime |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 50 | * @return redirect URI containing authorization code if |
| 51 | * successful. |
| 52 | * |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 53 | * @throws KustvaktException |
| 54 | * @throws OAuthSystemException |
| 55 | */ |
| 56 | public String requestAuthorizationCode (HttpServletRequest request, |
| margaretha | a2ce63d | 2018-06-28 10:11:43 +0200 | [diff] [blame] | 57 | OAuthAuthzRequest authzRequest, String username, |
| 58 | ZonedDateTime authenticationTime) |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 59 | throws OAuthSystemException, KustvaktException { |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 60 | |
| margaretha | da3c785 | 2018-06-14 20:35:11 +0200 | [diff] [blame] | 61 | String clientId = authzRequest.getClientId(); |
| 62 | OAuth2Client client = clientService.authenticateClientId(clientId); |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 63 | |
| margaretha | 33fa3d9 | 2018-07-26 13:50:17 +0200 | [diff] [blame] | 64 | String redirectUriStr = authzRequest.getRedirectURI(); |
| 65 | String verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr); |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 66 | |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 67 | URI redirectURI; |
| 68 | try { |
| 69 | redirectURI = new URI(verifiedRedirectUri); |
| 70 | } |
| 71 | catch (URISyntaxException e) { |
| 72 | throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI, |
| 73 | "Invalid redirect URI", OAuth2Error.INVALID_REQUEST); |
| 74 | } |
| 75 | |
| margaretha | 07a356a | 2018-07-11 19:12:21 +0200 | [diff] [blame] | 76 | String scope, code; |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 77 | try { |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 78 | //checkResponseType(authzRequest.getResponseType(), redirectURI); |
| margaretha | 0666ddb | 2018-08-02 16:54:04 +0200 | [diff] [blame] | 79 | code = codeGenerator.createRandomCode(); |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 80 | scope = createAuthorization(username, authzRequest.getClientId(), |
| margaretha | 33fa3d9 | 2018-07-26 13:50:17 +0200 | [diff] [blame] | 81 | redirectUriStr, authzRequest.getScopes(), code, |
| margaretha | a2ce63d | 2018-06-28 10:11:43 +0200 | [diff] [blame] | 82 | authenticationTime, null); |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 83 | } |
| 84 | catch (KustvaktException e) { |
| 85 | e.setRedirectUri(redirectURI); |
| 86 | throw e; |
| 87 | } |
| 88 | |
| 89 | OAuthResponse oAuthResponse; |
| 90 | try { |
| 91 | oAuthResponse = OAuthASResponse |
| 92 | .authorizationResponse(request, |
| 93 | Status.FOUND.getStatusCode()) |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 94 | .setCode(code).setScope(scope) |
| 95 | .location(verifiedRedirectUri) |
| margaretha | 56fd558 | 2018-06-18 22:14:51 +0200 | [diff] [blame] | 96 | .buildQueryMessage(); |
| 97 | } |
| 98 | catch (OAuthSystemException e) { |
| 99 | // Should not happen |
| 100 | KustvaktException ke = |
| 101 | new KustvaktException(StatusCodes.OAUTH2_SYSTEM_ERROR, |
| 102 | e.getMessage(), OAuth2Error.SERVER_ERROR); |
| 103 | ke.setRedirectUri(redirectURI); |
| 104 | throw ke; |
| 105 | } |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 106 | return oAuthResponse.getLocationUri(); |
| 107 | } |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 108 | |
| 109 | public OAuthProblemException checkRedirectUri (OAuthProblemException e, |
| 110 | String clientId, String redirectUri) { |
| margaretha | ef1883f | 2022-05-25 12:24:12 +0200 | [diff] [blame] | 111 | if (clientId !=null && !clientId.isEmpty()) { |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 112 | String registeredUri = null; |
| 113 | try { |
| 114 | OAuth2Client client = clientService.retrieveClient(clientId); |
| 115 | registeredUri = client.getRedirectURI(); |
| 116 | } |
| 117 | catch (KustvaktException e1) {} |
| 118 | |
| 119 | if (redirectUri != null && !redirectUri.isEmpty()) { |
| 120 | if (registeredUri != null && !registeredUri.isEmpty() |
| 121 | && !redirectUri.equals(registeredUri)) { |
| 122 | e.description("Invalid redirect URI"); |
| 123 | } |
| 124 | else { |
| 125 | e.setRedirectUri(redirectUri); |
| 126 | e.responseStatus(HttpStatus.SC_TEMPORARY_REDIRECT); |
| 127 | } |
| 128 | } |
| 129 | else if (registeredUri != null && !registeredUri.isEmpty()) { |
| 130 | e.setRedirectUri(registeredUri); |
| 131 | e.responseStatus(HttpStatus.SC_TEMPORARY_REDIRECT); |
| 132 | } |
| 133 | else { |
| 134 | e.description("Redirect URI is required"); |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | return e; |
| 139 | } |
| 140 | |
| 141 | public KustvaktException checkRedirectUri (KustvaktException e, |
| 142 | String clientId, String redirectUri){ |
| 143 | int statusCode = e.getStatusCode(); |
| 144 | if (!clientId.isEmpty() |
| 145 | && statusCode != StatusCodes.CLIENT_NOT_FOUND |
| margaretha | 9436ebe | 2022-04-22 11:48:37 +0200 | [diff] [blame^] | 146 | && statusCode != StatusCodes.AUTHORIZATION_FAILED |
| 147 | && statusCode != StatusCodes.INVALID_REDIRECT_URI) { |
| margaretha | ffb8950 | 2022-04-20 12:03:16 +0200 | [diff] [blame] | 148 | String registeredUri = null; |
| 149 | try { |
| 150 | OAuth2Client client = clientService.retrieveClient(clientId); |
| 151 | registeredUri = client.getRedirectURI(); |
| 152 | } |
| 153 | catch (KustvaktException e1) {} |
| 154 | |
| 155 | if (redirectUri != null && !redirectUri.isEmpty()) { |
| 156 | if (registeredUri != null && !registeredUri.isEmpty() |
| 157 | && !redirectUri.equals(registeredUri)) { |
| 158 | return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI, |
| 159 | "Invalid redirect URI", OAuth2Error.INVALID_REQUEST); |
| 160 | } |
| 161 | else { |
| 162 | try { |
| 163 | e.setRedirectUri(new URI(redirectUri)); |
| 164 | } |
| 165 | catch (URISyntaxException e1) { |
| 166 | return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI, |
| 167 | "Invalid redirect URI", OAuth2Error.INVALID_REQUEST); |
| 168 | } |
| 169 | e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT); |
| 170 | } |
| 171 | } |
| 172 | else if (registeredUri != null && !registeredUri.isEmpty()) { |
| 173 | try { |
| 174 | e.setRedirectUri(new URI(registeredUri)); |
| 175 | } |
| 176 | catch (URISyntaxException e1) { |
| 177 | return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI, |
| 178 | "Invalid redirect URI", OAuth2Error.INVALID_REQUEST); |
| 179 | } |
| 180 | e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT); |
| 181 | } |
| 182 | else { |
| 183 | return new KustvaktException(StatusCodes.MISSING_REDIRECT_URI, |
| 184 | "Redirect URI is required", OAuth2Error.INVALID_REQUEST); |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | return e; |
| 189 | } |
| margaretha | ec247dd | 2018-06-12 21:55:46 +0200 | [diff] [blame] | 190 | } |