This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit c1cab10e1ca4c1d9af04145f672677ae53e0e16d Author: Robert Munteanu <romb...@apache.org> AuthorDate: Thu Jul 6 14:59:42 2023 +0300 oidc-rp: expose API to refresh tokens --- .../apache/sling/servlets/oidc_rp/OidcClient.java | 2 +- .../sling/servlets/oidc_rp/impl/Converter.java | 52 +++++++++++++++ .../servlets/oidc_rp/impl/OidcClientImpl.java | 74 ++++++++++++---------- 3 files changed, 94 insertions(+), 34 deletions(-) diff --git a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/OidcClient.java b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/OidcClient.java index 1c17bb7c..a3b91188 100644 --- a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/OidcClient.java +++ b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/OidcClient.java @@ -28,5 +28,5 @@ public interface OidcClient { // void /* TODO OIDCTokens */ getOidcTokens(OidcConnection connection, String authenticationCode); - // void /* TODO Tokens*/ refreshAccessToken(OidcConnection connection, String refreshToken2) throws ParseException, IOException; + OidcTokens refreshTokens(OidcConnection connection, String refreshToken); } diff --git a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/Converter.java b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/Converter.java new file mode 100644 index 00000000..c1baf524 --- /dev/null +++ b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/Converter.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sling.servlets.oidc_rp.impl; + +import org.apache.sling.servlets.oidc_rp.OidcTokens; + +import com.nimbusds.oauth2.sdk.token.BearerAccessToken; +import com.nimbusds.oauth2.sdk.token.RefreshToken; +import com.nimbusds.openid.connect.sdk.token.OIDCTokens; + +public class Converter { + + public static OIDCTokens toNimbusOidcTokens(OidcTokens tokens) { + OIDCTokens nimbusTokens; + RefreshToken nimbusRefreshToken = new RefreshToken(tokens.refreshToken()); + BearerAccessToken nimbusAccessToken = new BearerAccessToken(tokens.accessToken(), tokens.expiresAt(), null); + if ( tokens.idToken() != null ) { + nimbusTokens = new OIDCTokens(tokens.idToken(), nimbusAccessToken, nimbusRefreshToken); + } else { + nimbusTokens = new OIDCTokens(nimbusAccessToken, nimbusRefreshToken); + } + + return nimbusTokens; + } + + public static OidcTokens toApiOidcTokens(OIDCTokens nimbusTokens) { + String accessToken = nimbusTokens.getAccessToken() != null ? nimbusTokens.getAccessToken().getValue() : null; + long expiresAt = nimbusTokens.getAccessToken() != null ? nimbusTokens.getAccessToken().getLifetime() : 0; + String refreshToken = nimbusTokens.getRefreshToken() != null ? nimbusTokens.getRefreshToken().getValue() : null; + String idToken = nimbusTokens.getIDTokenString(); + + return new OidcTokens(accessToken, expiresAt, refreshToken, idToken); + } + + private Converter() { + + } +} diff --git a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcClientImpl.java b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcClientImpl.java index f51112a8..48fa6388 100644 --- a/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcClientImpl.java +++ b/org.apache.sling.servlets.oidc-rp/src/main/java/org/apache/sling/servlets/oidc_rp/impl/OidcClientImpl.java @@ -27,11 +27,11 @@ import java.nio.charset.StandardCharsets; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.servlets.oidc_rp.OidcClient; import org.apache.sling.servlets.oidc_rp.OidcConnection; +import org.apache.sling.servlets.oidc_rp.OidcTokens; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import com.nimbusds.oauth2.sdk.AccessTokenResponse; import com.nimbusds.oauth2.sdk.AuthorizationGrant; import com.nimbusds.oauth2.sdk.ParseException; import com.nimbusds.oauth2.sdk.RefreshTokenGrant; @@ -39,17 +39,17 @@ import com.nimbusds.oauth2.sdk.ResponseType; import com.nimbusds.oauth2.sdk.Scope; import com.nimbusds.oauth2.sdk.TokenErrorResponse; import com.nimbusds.oauth2.sdk.TokenRequest; -import com.nimbusds.oauth2.sdk.TokenResponse; import com.nimbusds.oauth2.sdk.auth.ClientAuthentication; import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic; import com.nimbusds.oauth2.sdk.auth.Secret; import com.nimbusds.oauth2.sdk.id.ClientID; import com.nimbusds.oauth2.sdk.id.State; import com.nimbusds.oauth2.sdk.token.RefreshToken; -import com.nimbusds.oauth2.sdk.token.Tokens; import com.nimbusds.openid.connect.sdk.AuthenticationRequest; import com.nimbusds.openid.connect.sdk.Nonce; +import com.nimbusds.openid.connect.sdk.OIDCTokenResponse; import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata; +import com.nimbusds.openid.connect.sdk.token.OIDCTokens; @Component(service = { OidcClientImpl.class, OidcClient.class }) public class OidcClientImpl implements OidcClient { @@ -60,37 +60,45 @@ public class OidcClientImpl implements OidcClient { public OidcClientImpl(@Reference OidcProviderMetadataRegistry providerMetadataRegistry) { this.providerMetadataRegistry = providerMetadataRegistry; } + + @Override + public OidcTokens refreshTokens(OidcConnection connection, String refreshToken2) { + return Converter.toApiOidcTokens(refreshTokensInternal(connection, refreshToken2)); + } + + public OIDCTokens refreshTokensInternal(OidcConnection connection, String refreshToken2) { - // TODO - can't make API when returning Nimbus Tokens - public Tokens refreshAccessToken(OidcConnection connection, String refreshToken2) throws ParseException, IOException { - - // Construct the grant from the saved refresh token - RefreshToken refreshToken = new RefreshToken(refreshToken2); - AuthorizationGrant refreshTokenGrant = new RefreshTokenGrant(refreshToken); - - // The credentials to authenticate the client at the token endpoint - ClientID clientID = new ClientID(connection.clientId()); - Secret clientSecret = new Secret(connection.clientSecret()); - ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret); - - // The token endpoint - URI tokenEndpoint = providerMetadataRegistry.getProviderMetadata(connection.baseUrl()).getTokenEndpointURI(); - - // Make the token request - TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, refreshTokenGrant); - - TokenResponse response = TokenResponse.parse(request.toHTTPRequest().send()); - - if (! response.indicatesSuccess()) { - // We got an error response... - TokenErrorResponse errorResponse = response.toErrorResponse(); - throw new RuntimeException("Failed refreshing the access token " + errorResponse.getErrorObject().getCode() + " : " + errorResponse.getErrorObject().getDescription()); - } - - AccessTokenResponse successResponse = response.toSuccessResponse(); - - // Get the access token, the refresh token may be updated - return successResponse.getTokens(); + try { + // Construct the grant from the saved refresh token + RefreshToken refreshToken = new RefreshToken(refreshToken2); + AuthorizationGrant refreshTokenGrant = new RefreshTokenGrant(refreshToken); + + // The credentials to authenticate the client at the token endpoint + ClientID clientID = new ClientID(connection.clientId()); + Secret clientSecret = new Secret(connection.clientSecret()); + ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret); + + // The token endpoint + URI tokenEndpoint = providerMetadataRegistry.getProviderMetadata(connection.baseUrl()).getTokenEndpointURI(); + + // Make the token request + TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, refreshTokenGrant); + + OIDCTokenResponse response = OIDCTokenResponse.parse(request.toHTTPRequest().send()); + + if (! response.indicatesSuccess()) { + // We got an error response... + TokenErrorResponse errorResponse = response.toErrorResponse(); + throw new RuntimeException("Failed refreshing the access token " + errorResponse.getErrorObject().getCode() + " : " + errorResponse.getErrorObject().getDescription()); + } + + OIDCTokenResponse successResponse = response.toSuccessResponse(); + + // Get the access token, the refresh token may be updated + return successResponse.getOIDCTokens(); + } catch (ParseException |IOException e) { + throw new RuntimeException(e); + } } @Override