简体   繁体   中英

Spring OAuth2 and JWT Authentication information

I have a Spring Boot (1.3.x) application acting as a resource server, that I can pass a JWT token from Keycloak in the Authorization header and am cleared to access some endpoints. The issue I am running into is that I can't get information which is in my JWT token in the Authorization object.

SecurityContext sc = SecurityContextHolder.getContext();
Authentication a = sc.getAuthentication(); //OR OAuth2Authentication oa = (OAuth2Authentication)a;
Object p = a.getPrincipal();

and p will hold the name of the client_id if I have the IDP put it in the token.

isClientOnly() returns true. Why?

I'd love to be able to get my user's name, and grants, but none of that is found. If I don't have a client_id, it's actually null.

I've tried to understand if I somehow have to configure something about how JWT tokens are handled after being validated so the right info gets into the Authentication object, but I'm totally confused. How can I make that happen?

Spring Boot's great how you can do so little to get something running, but at the same time, I'm at a loss where to start or what's really even set in the first place...

my application.yml:

server:
  servlet-path: /*

security:
  oauth2:
    resource:
      jwt:
        keyValue:
          -----BEGIN PUBLIC KEY-----
          MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmFbcU2Q6WZwUjEBvsZP8kIiE5mmctTGq1SOrPN5U4MkaTVs/zs2cWf+fhIE4WQ+dF9xTPxrJCGkwCMMXEhReFadOvzW8S3VdKdhng/j2GUbleU1QLSOGLhXu2+ODxeToZGpXIxtJiK2wE0JI9T6UwAe9j/stp4pMUzQubkG9acA+lpA5+zaCylLHysNFlSO1cTgzTdIZpXQGu5nkmyz7xT6vq8n2qAsD5GG5JRpBAac6L10Hnvl1YbwnPfi1T+IZSq7FdSpGJmYeOiPhJF0j7qYOMcaQgOfzoQGBhXslIHZeeaBIuUM6QFgZacJsVxdQoRvMronuuacnS+bngMEVDQIDAQAB
          -----END PUBLIC KEY-----
logging:
  level:
    org:
      springframework:
        security: DEBUG

my SecurityConfig.java:

package com.something.me;

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@Configuration
@EnableOAuth2Sso
@EnableResourceServer
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {

        //TODO add scope and role restrictions...
        http.authorizeRequests().anyRequest().authenticated();
}

You maybe got confused with the principle....As far as I know you can inject it like other beans...or access it in a contoller action like this

@Controller
class MyController {
  @RequestMapping("/greeting") 
  public Principal greeting(Principal user) {
    return user;
  }
}

Beside of that, I do not see any JwtConfiguration as well as token store beans in your code....

You have to configure something like this (assuming your key is saved in a public.cert in your resources directory)

@Configuration
public class JwtConfiguration {
    @Autowired
    JwtAccessTokenConverter jwtAccessTokenConverter;


    @Bean
    @Qualifier("tokenStore")
    public TokenStore tokenStore() {

        System.out.println("Created JwtTokenStore");
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        JwtAccessTokenConverter converter =  new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.cert");
        String publicKey = null;
        try {
            publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        return converter;
    }
}

Hope I could help. Maybe my article can give a closer explaination :)

The token store part got me part way... It appears my issue lies in the fact that I'm using Keycloak and it is returning openid connect tokens where the field names are mostly different. I hard-coded some fields like 'user_name' in the Keycloak token and all of a sudden could get a principal object, although not with much info in it.

So I was mistaken in thinking Spring's OAuth2 JWT stuff was just going to automatically work with any JWT. Starting working with the keycloak adaptor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM