Merge pull request #32 from dBucik/sign_refresh_tokens

feat: 🎸 Sign refresh tokens
pull/1580/head
Dominik František Bučík 2021-11-08 07:55:46 +01:00 committed by GitHub
commit 152b1448b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 6 deletions

View File

@ -20,13 +20,23 @@
*/
package cz.muni.ics.oauth2.service.impl;
import static cz.muni.ics.oauth2.service.IntrospectionResultAssembler.SCOPE;
import static cz.muni.ics.oauth2.service.IntrospectionResultAssembler.SCOPE_SEPARATOR;
import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.CODE_CHALLENGE;
import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.CODE_CHALLENGE_METHOD;
import static cz.muni.ics.openid.connect.request.ConnectRequestParameters.CODE_VERIFIER;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jwt.SignedJWT;
import cz.muni.ics.jwt.signer.service.JWTSigningAndValidationService;
import cz.muni.ics.oauth2.model.OAuth2AccessTokenEntity;
import cz.muni.ics.oauth2.model.OAuth2RefreshTokenEntity;
import cz.muni.ics.oauth2.repository.OAuth2TokenRepository;
import cz.muni.ics.openid.connect.config.ConfigurationPropertiesBean;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -101,6 +111,12 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
@Autowired
private ApprovedSiteService approvedSiteService;
@Autowired
private JWTSigningAndValidationService jwtService;
@Autowired
private ConfigurationPropertiesBean configBean;
@Override
public Set<OAuth2AccessTokenEntity> getAllAccessTokensForUser(String userName) {
return tokenRepository.getAccessTokensByUserName(userName);
@ -262,7 +278,6 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken();
JWTClaimsSet.Builder refreshClaims = new JWTClaimsSet.Builder();
// make it expire if necessary
if (client.getRefreshTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L));
@ -272,19 +287,29 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
// set a random identifier
refreshClaims.jwtID(UUID.randomUUID().toString());
refreshClaims.issuer(configBean.getIssuer());
// TODO: add issuer fields, signature to JWT
String audience = client.getClientId();
if (!Strings.isNullOrEmpty(audience)) {
refreshClaims.audience(Lists.newArrayList(audience));
}
PlainJWT refreshJwt = new PlainJWT(refreshClaims.build());
refreshToken.setJwt(refreshJwt);
JWTClaimsSet claims = refreshClaims.build();
JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm();
JWSHeader header = new JWSHeader(signingAlg, JOSEObjectType.JWT, null, null, null, null, null, null, null, null,
jwtService.getDefaultSignerKeyId(), true, null, null);
SignedJWT signed = new SignedJWT(header, claims);
jwtService.signJwt(signed);
refreshToken.setJwt(signed);
//Add the authentication
refreshToken.setAuthenticationHolder(authHolder);
refreshToken.setClient(client);
// save the token first so that we can set it to a member of the access token (NOTE: is this step necessary?)
OAuth2RefreshTokenEntity savedRefreshToken = tokenRepository.saveRefreshToken(refreshToken);
return savedRefreshToken;
return tokenRepository.saveRefreshToken(refreshToken);
}
@Override

View File

@ -17,9 +17,11 @@
*******************************************************************************/
package cz.muni.ics.oauth2.service.impl;
import cz.muni.ics.jwt.signer.service.JWTSigningAndValidationService;
import cz.muni.ics.oauth2.model.OAuth2AccessTokenEntity;
import cz.muni.ics.oauth2.model.OAuth2RefreshTokenEntity;
import cz.muni.ics.oauth2.repository.OAuth2TokenRepository;
import cz.muni.ics.openid.connect.config.ConfigurationPropertiesBean;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@ -50,6 +52,7 @@ import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import static com.google.common.collect.Sets.newHashSet;
import static com.nimbusds.jose.JWSAlgorithm.RS256;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
@ -91,6 +94,7 @@ public class TestDefaultOAuth2ProviderTokenService {
private OAuth2AccessTokenEntity accessToken;
private String refreshTokenValue = "refresh_token_value";
private String userName = "6a50ac11786d402a9591d3e592ac770f";
private final String issuer = "https://issuer.com/oidc/";
private TokenRequest tokenRequest;
// for use when refreshing access tokens
@ -114,6 +118,12 @@ public class TestDefaultOAuth2ProviderTokenService {
@Mock
private SystemScopeService scopeService;
@Mock
private ConfigurationPropertiesBean configBean;
@Mock
private JWTSigningAndValidationService jwtService;
@InjectMocks
private DefaultOAuth2ProviderTokenService service;
@ -219,6 +229,11 @@ public class TestDefaultOAuth2ProviderTokenService {
}
});
when(configBean.getIssuer()).thenReturn(issuer);
when(jwtService.getDefaultSigningAlgorithm()).thenReturn(RS256);
String keyId = "kid1";
when(jwtService.getDefaultSignerKeyId()).thenReturn(keyId);
}
/**