Skip to content

Commit

Permalink
Refactor token attribute retrieval in reactive security. #deploy-idpo…
Browse files Browse the repository at this point in the history
…rten-frontend

Replaced direct Jwt token access with a context-based approach to support both Jwt and OAuth2 authentication tokens. Introduced a new `Oauth2Resolver` utility for secure handling of tokens and expiration checks. This improves flexibility and enhances token handling consistency.
  • Loading branch information
krharum committed Dec 17, 2024
1 parent 3ba51fc commit d7b1a9c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package no.nav.testnav.libs.reactivesecurity.action;

import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.concurrent.Callable;

@Component
@RequiredArgsConstructor
public class GetAuthenticatedUserId extends JwtResolver implements Callable<Mono<String>> {
public class GetAuthenticatedUserId implements Callable<Mono<String>> {

private final GetAuthenticatedResourceServerType getAuthenticatedResourceServerType;

Expand All @@ -23,6 +28,23 @@ public Mono<String> call() {
}

private Mono<String> getTokenAttribute(String attribute) {
return getJwtAuthenticationToken().map(value -> value.getTokenAttributes().get(attribute).toString());

return ReactiveSecurityContextHolder
.getContext()
.map(SecurityContext::getAuthentication)
.map(context -> getTokenAttribute(context, attribute));
}

private String getTokenAttribute(Authentication context, String attribute) {

if (context instanceof JwtAuthenticationToken jwtAuthenticationToken) {
return jwtAuthenticationToken.getTokenAttributes().get(attribute).toString();

} else if (context instanceof OAuth2AuthenticationToken oauth2AuthenticationToken) {
return oauth2AuthenticationToken.getPrincipal().getAttributes().get(attribute).toString();

} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package no.nav.testnav.libs.reactivesecurity.action;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.jwt.Jwt;
import reactor.core.publisher.Mono;

import java.time.Instant;
import java.time.ZonedDateTime;

@Slf4j
@UtilityClass
public class Oauth2Resolver {

public static Mono<OAuth2AuthenticationToken> getOauth2AuthenticationToken() {
return ReactiveSecurityContextHolder
.getContext()
.switchIfEmpty(Mono.error(new JwtResolverException("ReactiveSecurityContext is empty")))
.doOnNext(context -> log.info("context.authentication {}", context.getAuthentication()))
.map(SecurityContext::getAuthentication)
.map(OAuth2AuthenticationToken.class::cast)
.doOnError(throwable -> log.warn("Klarte ikke hente Jwt Auth Token", throwable))
.doOnSuccess(jwtAuthenticationToken -> {
Jwt credentials = (Jwt) jwtAuthenticationToken.getCredentials();
Instant expiresAt = credentials.getExpiresAt();
if (expiresAt == null || expiresAt.isBefore(ZonedDateTime.now().toInstant().plusSeconds(120))) {
throw new CredentialsExpiredException("Jwt er utløpt eller utløper innen kort tid");
}
});
}
}

0 comments on commit d7b1a9c

Please sign in to comment.