I work with springboot and use oath2 (JWT).
My token is the next
token
I want to get the payload from a controller or a filter but i dont know how.
I try this but it doesn't work
#GetMapping("/user")
public String getB(#AuthenticationPrincipal Jwt principal, #RequestHeader("refresh") String refresh) {
System.out.println(principal.getClaims());;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object details = authentication.getDetails();
if ( details instanceof OAuth2AuthenticationDetails ){
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails)details;
Map<String, Object> decodedDetails = (Map<String, Object>)oAuth2AuthenticationDetails.getDecodedDetails();
System.out.println( decodedDetails.get("time_created") );
}
(SORRY FOR MY ENGLISH)
I can get a details with the next code:
get access token
decode this token
add decode token in a map
get detail that i need by key in the map
#GetMapping("/user")
public String getB(OAuth2Authentication auth) throws JsonMappingException, JsonProcessingException {
final OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) auth.getDetails();
// token
String accessToken = details.getTokenValue();
System.out.println(accessToken);
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, ?> tokenData = parser.parseMap(JwtHelper.decode(accessToken).getClaims());
String customField = (String) tokenData.get("time_created");
Related
How do I get the roles and attributes of a user using the Java Client of Keycloak? Below is the code that I have written to get the access token of a user, however, I am not able to find the way to get the roles assigned to that user.
Configuration configuration = new Configuration();
configuration.setRealm("foo");
configuration.setResource("foo");
configuration.setBearerOnly(Boolean.TRUE);
configuration.setAuthServerUrl("http://localhost:8080");
configuration.setCredentials(Map.of("secret", "FV3P4ajYHedAUDtOa55EX5nzK8zc6jUA"));
AuthzClient authzClient = AuthzClient.create(configuration);
AuthorizationRequest request = new AuthorizationRequest();
AuthorizationResponse authorize = authzClient.authorization("john.doe", "john.doe").authorize(request);
String token = authorize.getToken();
log.info("Auth bearer token is {}", token);
You have the token as a String, namely:
String token = authorize.getToken();
now you just need to parse it to get the Realm and Client roles, which are encoded in the token. For that you can use the class TokenVerifier from org.keycloak.TokenVerifier.
For example:
try {
AccessToken token = TokenVerifier.create(tokenString, AccessToken.class).getToken();
System.out.printf("Realm 'foo' = Roles %s%n", token.getRealmAccess().getRoles());
token.getResourceAccess().forEach((k, v) -> System.out.printf("Client '%s' = Roles '%s'%n", k, v.getRoles()));
} catch (VerificationException e) {
...
}
I need your help on this matter. It looks like I have the Schrodinger's cookie!
I am using Spring Boot with Java. I can successfully create the cookie like this:
public String createNewCookie(HttpServletResponse response) {
// create a cookie
String newToken = AccountsService.generateRandomCode(6);
Cookie cookie = new Cookie("clrToken", newToken);
cookie.setMaxAge(10 * 365 * 24 * 60 * 60); // expires in 10 years
cookie.setSecure(true);
cookie.setHttpOnly(true);
//add cookie to response
response.addCookie(cookie);
return newToken;
}
I can easily fetch created cookie and read its value (token) in one of my controllers like this:
#PostMapping(value = "/public/save",
produces = MediaType.APPLICATION_JSON_VALUE)
#Operation(summary = "Save new affiliate click into database")
public ResponseEntity<AffiliateClickDto> saveAffiliateClick
(#RequestParam Long serviceId,
#CookieValue(value = "clrToken", defaultValue = "") final String token) {
return new ResponseEntity<>(affiliateClickService.saveAffiliateClick(serviceId, token), HttpStatus.OK);
}
But I can not fetch that same cookie from another endpoint in my other controller.
#GetMapping(value = "/public/servicesByFilters",
produces = MediaType.APPLICATION_JSON_VALUE)
#Operation(summary = "Get all Providers Services for filters")
public ResponseEntity<List<ServiceResultPageDTO>> getAllProvidersServicesForFilters
(#RequestParam final Map<String, String> params,
#CookieValue(value = "clrToken", defaultValue = "") final String token) {
return new ResponseEntity<>(services.getAllProvidersServiceForFilters(params, token), HttpStatus.OK);
}
I get an empty String for The String token parameter value.
I allso tried to use the loop to iterate through cookies, but I do not get my "clrToken" at this second endpoint. I can access some other cookies.
public String readAllCookies(HttpServletRequest request) {
String token="";
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
if (Objects.equals(c.getName(), "clrToken")) {
token = c.getValue();
break;
}
}
return token;
}
Who eat my cookie??? :D Does anyone have idea what is happening here? If you need some other info, please ask.
I'm trying to get an Access Token from Keycloak over SpringBoot and did try the following example. But the KeycloakAuthenticationToken token is null.
Does someone know another approach to get an Access Token?
#GetMapping("/token")
public String getToken(HttpServletRequest request) throws IOException {
KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) request.getUserPrincipal();
RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) token.getAccount().getKeycloakSecurityContext();
KeycloakSecurityContext context = token.getAccount().getKeycloakSecurityContext();
String accessTokenPretty = JsonSerialization.writeValueAsPrettyString(session.getToken());
String idTokenPretty = JsonSerialization.writeValueAsPrettyString(session.getIdToken());
RefreshToken refreshToken;
try {
refreshToken = new JWSInput(session.getRefreshToken()).readJsonContent(RefreshToken.class);
} catch (JWSInputException e) {
throw new IOException(e);
}
String refreshTokenPretty = JsonSerialization.writeValueAsPrettyString(refreshToken);
return refreshTokenPretty;
}
Seems like I can get a token like this with ('org.keycloak:keycloak-admin-client'):
Keycloak keycloak = KeycloakBuilder.builder() //
.serverUrl(serverUrl) //
.realm(realm) //
.grantType(OAuth2Constants.PASSWORD) //
.clientId(clientId) //
.clientSecret(clientSecret) //
.username(userName) //
.password(password) //
.build();
AccessTokenResponse tok = keycloak.tokenManager().getAccessToken();
If someone knows a more elegant way, I would appreciate if you let me know :)
Thanks in advance!
Try the following:
HttpEntity<MultiValueMap<String, String>> request =
new TokenRequest.Builder(clientID, OAuth2Constants.PASSWORD)
.add("username", userName)
.add("password", password)
.build();
ResponseEntity<String> response = restTemplate.postForEntity( postUrl, request , String.class );
return response.getBody();
and the helper class:
public class TokenRequest {
public static class Builder{
MultiValueMap<String, String> data;
public Builder(String clientID, String grant_type){
data = new LinkedMultiValueMap<>();
data.put("client_id", Collections.singletonList(clientID));
data.put("grant_type", Collections.singletonList(grant_type));
}
public Builder add(String key, String value){
data.put(key, Collections.singletonList(value));
return this;
}
public HttpEntity<MultiValueMap<String, String>> build(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
return new HttpEntity<>(data, headers);
}
}
private TokenRequest(){
}
}
Try this:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
KeycloakAuthenticationToken keycloakAuthenticationToken = (KeycloakAuthenticationToken) request.getUserPrincipal();
KeycloakPrincipal<KeycloakSecurityContext> principal = (KeycloakPrincipal) keycloakAuthenticationToken.getPrincipal();
String token = principal.getKeycloakSecurityContext().getIdTokenString();
I have two service connected to a registry, one of them need to query some data from the other, the token need to be passed to the endpoint.
I Have tried the following but it didn't work, the endpoint act as if no token is provided.
#GetMapping("/api/users/find")
#Headers("Authorization: Bearer {token}")
Optional<UserDTO> findUserByEmail(
#Param("token") String token, #RequestParam("email") String email);
#GetMapping("/api/users/find")
Optional<UserDTO> findUserByEmail(
#RequestHeaders("Authorization") String token, #RequestParam("email") String email);
#GetMapping("/api/users/find")
Optional<UserDTO> findUserByEmail(
#HeaderMap Map<String, Object> headers , #RequestParam("email") String email);
Should work lke this #RequestHeader(value = "Authorization") String authorization, but make sure you pass the right value, must be something like Bearer token.
Your this code is absolutely correct.
#GetMapping("/api/users/find")
Optional<UserDTO> findUserByEmail(
#RequestHeaders("Authorization") String token, #RequestParam("email") String email);
Just when you are calling this particular method add "Bearer " in front of the value of the token
token = "Bearer " + token;
findUserByEmail(token,email);
Create Header like this and pass to your feign client
private HttpHeaders getHeaders(final HttpServletRequest httpServletRequest) {
final HttpHeaders headers = new HttpHeaders();
headers.add("authorization", httpServletRequest.getHeader("authorization"));
return headers;
Example 1
Or very simple add intercepter
#Component
public class AuthFeignInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate template) {
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
final HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
template.header(HttpHeaders.AUTHORIZATION, httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION));
}
}
}
Example 2
I'm using socialauth to handle oauth authentication. Also I have basic login&password authentication(not implemented. but service method exists).
public Map<String, String> oauthAuthentication(String source, String callback) throws Exception {
Map<String, String> map = new HashMap<>();
SocialAuthConfig config = new SocialAuthConfig();
config.load("oauth_consumer.properties");
SocialAuthManager socialAuthManager = new SocialAuthManager();
socialAuthManager.setSocialAuthConfig(config);
String url = socialAuthManager.getAuthenticationUrl(source, callback);
map.put("url", url);
map.put("token", socialAuthManager.getCurrentAuthProvider().getAccessGrant().getKey());
return map;
}
public String loginPasswordAuthentication(String username, String password) {
return null;
}
But how to add spring security here? What should I keep and where? What authentication information I should keep? I have context for it and it works fine (intercept request and redirect to login page).