The expiration time of a JWT can be set by configuring micronaut.security.token.jwt.generator.access-token-expiration.
Is it possible to have a custom value for individually issued JWT tokens? Searching the documentation I haven't found any useful information except you can replace the BearerTokenRenderer
and return a custom response.
public AccessRefreshToken render(Integer expiresIn, String accessToken, @Nullable String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, ***customValue**);
}
Will returning a different value for expires_in
work in this case?
CodePudding user response:
According to micronaut documentation - pt 9.3.5
You can replace ClaimGenerator with your own: ClaimGenerator
Which has a method with parameter Integer expiration
You can replace classes by using @Replaces
annotation like described here:
https://micronaut-projects.github.io/micronaut-core/latest/guide/#replaces
I hope that solves your issue
CodePudding user response:
The solution is to extend the JwTClaimsSetGenerator
@Replaces(JWTClaimsSetGenerator.class)
@Singleton
public class CustomClaimsGenerator extends JWTClaimsSetGenerator {
private static final Logger LOG = LoggerFactory.getLogger(CustomClaimsGenerator.class);
private static final String ROLES_KEY = "rolesKey";
private final TokenConfiguration tokenConfiguration;
private final JwtIdGenerator jwtIdGenerator;
private final ClaimsAudienceProvider claimsAudienceProvider;
private final String appName;
/**
* @param tokenConfiguration Token Configuration
* @param jwtIdGenerator Generator which creates unique JWT ID
* @param claimsAudienceProvider Provider which identifies the recipients that the JWT is intended for.
* @param applicationConfiguration The application configuration
*/
public CustomClaimsGenerator(TokenConfiguration tokenConfiguration,@Nullable JwtIdGenerator jwtIdGenerator, @Nullable ClaimsAudienceProvider claimsAudienceProvider, ApplicationConfiguration applicationConfiguration) {
super(tokenConfiguration, jwtIdGenerator, claimsAudienceProvider, applicationConfiguration);
this.tokenConfiguration = tokenConfiguration;
this.jwtIdGenerator = jwtIdGenerator;
this.claimsAudienceProvider = claimsAudienceProvider;
this.appName = applicationConfiguration != null ? applicationConfiguration.getName().orElse(Environment.MICRONAUT) : Environment.MICRONAUT;
}
/**
* @param authentication Authenticated user's representation.
* @param expiration expiration time in seconds
* @return The authentication claims
*/
@Override
public Map<String, Object> generateClaims(Authentication authentication, @Nullable Integer expiration) {
expiration = 1000; //works with this value
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
populateIat(builder);
populateExp(builder, 15);
populateJti(builder);
populateIss(builder);
populateAud(builder);
populateNbf(builder);
populateWithAuthentication(builder, authentication);
if (LOG.isDebugEnabled()) {
LOG.debug("Generated claim set: {}", builder.build().toJSONObject());
}
return builder.build().getClaims();
}
/**
* Populates iss claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.1">iss (Issuer) Claim</a>
*/
protected void populateIss(JWTClaimsSet.Builder builder) {
if (appName != null) {
builder.issuer(appName); // iss
}
}
/**
* Populates sub claim.
*
* @param builder The Claims Builder
* @param authentication Authenticated user's representation.
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.2">sub (Subject) Claim</a>
*/
protected void populateSub(JWTClaimsSet.Builder builder, Authentication authentication) {
builder.subject(authentication.getName()); // sub
}
/**
* Populates aud claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.3">aud (Audience) Claim</a>
*/
protected void populateAud(JWTClaimsSet.Builder builder) {
if (claimsAudienceProvider != null) {
builder.audience(claimsAudienceProvider.audience()); // aud
}
}
/**
* Populates exp claim.
*
* @param builder The Claims Builder
* @param expiration expiration time in seconds
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.4">exp (ExpirationTime) Claim</a>
*/
protected void populateExp(JWTClaimsSet.Builder builder, @Nullable Integer expiration) {
if (expiration != null) {
LOG.debug("Setting expiration to {}", expiration);
System.out.print(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS)));
builder.expirationTime(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS))); // exp
}
}
/**
* Populates nbf claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.5">nbf (Not Before) Claim</a>
*/
protected void populateNbf(JWTClaimsSet.Builder builder) {
builder.notBeforeTime(new Date()); // nbf
}
/**
* Populates iat claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.6">iat (Issued At) Claim</a>
*/
protected void populateIat(JWTClaimsSet.Builder builder) {
builder.issueTime(new Date()); // iat
}
/**
* Populates jti claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.7">jti (JWT ID) Claim</a>
*/
protected void populateJti(JWTClaimsSet.Builder builder) {
if (jwtIdGenerator != null) {
builder.jwtID(jwtIdGenerator.generateJtiClaim()); // jti
}
}
/**
* Populates Claims with Authentication object.
*
* @param builder the Claims Builder
* @param authentication Authenticated user's representation.
*/
protected void populateWithAuthentication(JWTClaimsSet.Builder builder, Authentication authentication) {
populateSub(builder, authentication);
authentication.getAttributes().forEach(builder::claim);
String rolesKey = tokenConfiguration.getRolesName();
if (!rolesKey.equalsIgnoreCase(TokenConfiguration.DEFAULT_ROLES_NAME)) {
builder.claim(ROLES_KEY, rolesKey);
}
builder.claim(rolesKey, authentication.getRoles());
}
/**
* @param oldClaims The old claims to use as a base in the new token generation.
* @param expiration expiration time in seconds
* @return Instance of {@link JWTClaimsSet}
*/
@Override
public Map<String, Object> generateClaimsSet(Map<String, ?> oldClaims, Integer expiration) {
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
List<String> excludedClaims = Arrays.asList(JwtClaims.EXPIRATION_TIME, JwtClaims.ISSUED_AT, JwtClaims.NOT_BEFORE);
for (String k : oldClaims.keySet()
.stream()
.filter(p -> !excludedClaims.contains(p))
.collect(Collectors.toList())) {
builder.claim(k, oldClaims.get(k));
}
populateExp(builder, expiration);
populateIat(builder);
populateNbf(builder);
return builder.build().getClaims();
}
}