com.predic8.membrane.core.interceptor.oauth2client.rf.token.AccessTokenRefresher Maven / Gradle / Ivy
/* Copyright 2024 predic8 GmbH, www.predic8.com
Licensed 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 com.predic8.membrane.core.interceptor.oauth2client.rf.token;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.interceptor.oauth2.authorizationservice.AuthorizationService;
import com.predic8.membrane.core.interceptor.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static com.predic8.membrane.core.interceptor.oauth2client.OAuth2Resource2Interceptor.WANTED_SCOPE;
import static com.predic8.membrane.core.interceptor.oauth2client.rf.JsonUtils.isJson;
public class AccessTokenRefresher {
private static final Logger log = LoggerFactory.getLogger(AccessTokenRefresher.class);
private final Cache synchronizers = CacheBuilder.newBuilder()
.expireAfterAccess(1, TimeUnit.MINUTES)
.build();
private AuthorizationService auth;
private TokenResponseHandler tokenResponseHandler;
private boolean onlyRefreshToken;
public void init(AuthorizationService auth, boolean onlyRefreshToken) {
this.auth = auth;
this.onlyRefreshToken = onlyRefreshToken;
tokenResponseHandler = new TokenResponseHandler();
tokenResponseHandler.init(auth);
}
public void refreshIfNeeded(Session session, Exchange exc) {
String wantedScope = (String) exc.getProperty(WANTED_SCOPE);
if (!refreshingOfAccessTokenIsNeeded(session, wantedScope)) {
return;
}
synchronized (getTokenSynchronizer(session)) {
try {
refreshAccessToken(session, wantedScope);
exc.setProperty(Exchange.OAUTH2, session.getOAuth2AnswerParameters(wantedScope));
} catch (Exception e) {
log.warn("Failed to refresh access token, clearing session and restarting OAuth2 flow.", e);
session.clearAuthentication();
}
}
}
private void refreshAccessToken(Session session, String wantedScope) throws Exception {
var params = session.getOAuth2AnswerParameters();
var response = auth.refreshTokenRequest(session, params, wantedScope);
if (!response.isOk()) {
response.getBody().read();
throw new RuntimeException("Statuscode from authorization server for refresh token request: " + response.getStatusCode());
}
if (!isJson(response)) {
throw new RuntimeException("Refresh Token response is no JSON.");
}
var json = new ObjectMapper().readValue(response.getBodyAsStreamDecoded(), new TypeReference