0

I have a Spring SSO Application using my Spring OAuth2 server.

This is my application.yml:

security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: atlas
      clientSecret: cerberus
      accessTokenUri: http://localhost:8180/guardiao/oauth/token
      userAuthorizationUri: http://localhost:8180/guardiao/oauth/authorize
    resource:
      userInfoUri: http://localhost:8180/guardiao/user/me

When the user try to access any URL from the application it redirects to the OAuth server login. After login the user is sent back to the application.

The application then ask the OAuth server for the user details (http://localhost:8180/guardiao/user/me):

@RequestMapping("/user/me")
public @ResponseBody Principal user(Principal principal) {
    System.out.println("Requesting logged user..." + principal.getName() );
    return principal;
} 

The principal object is sent to application. All is working fine.

My question: is there some way to:

1) At client side intercept the comming Principal object and ask the server for the user complements?

@RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public  @ResponseBody MyCustomUser getUser(@PathVariable("id") long id) {
    System.out.println("Fetching User with id " + id);
    // get from database by ID (the Principal's username attribute)
    return user;
}

2) Send complete user details at first request (/user/me)? I think this may cause trouble at client side because it is expecting a Principal object...

This is the Principal (me endpoint)

{
    "authorities": [
        {
            "authority": "ROLE_ADMIN"
        }
    ],
    "details": {
        "remoteAddress": "0:0:0:0:0:0:0:1",
        "sessionId": null,
        "tokenValue": "eeddd69d-a6f1-488c-aec3-985ed71d4ee0",
        "tokenType": "Bearer",
        "decodedDetails": null
    },
    "authenticated": true,
    "userAuthentication": {
        "authorities": [
            {
                "authority": "ROLE_ADMIN"
            }
        ],
        "details": {
            "grant_type": "password",
            "username": "admin"
        },
        "authenticated": true,
        "principal": {
            "password": null,
            "username": "admin",
            "authorities": [
                {
                    "authority": "ROLE_ADMIN"
                }
            ],
            "accountNonExpired": true,
            "accountNonLocked": true,
            "credentialsNonExpired": true,
            "enabled": true
        },
        "credentials": null,
        "name": "admin"
    },
    "principal": {
        "password": null,
        "username": "admin",
        "authorities": [
            {
                "authority": "ROLE_ADMIN"
            }
        ],
        "accountNonExpired": true,
        "accountNonLocked": true,
        "credentialsNonExpired": true,
        "enabled": true
    },
    "oauth2Request": {
        "clientId": "cerberus",
        "scope": [
            "read",
            "write",
            "trust",
            "user_info"
        ],
        "requestParameters": {
            "grant_type": "password",
            "username": "admin"
        },
        "resourceIds": [],
        "authorities": [
            {
                "authority": "ROLE_TRUSTED_CLIENT"
            },
            {
                "authority": "ROLE_CLIENT"
            }
        ],
        "approved": true,
        "refresh": false,
        "redirectUri": null,
        "responseTypes": [],
        "extensions": {},
        "grantType": "password",
        "refreshTokenRequest": null
    },
    "clientOnly": false,
    "credentials": "",
    "name": "admin"
}

and this is my custom User:

{
    "id": 1,
    "username": "admin",
    "fullName": "Administrator",
    "enabled": true,
    "roles": [
        {
            "id": 1,
            "roleName": "ROLE_ADMIN"
        }
    ],
    "profileImage": "nophoto.png",
    "funcao": "Cerberus Admin",
    "setor": "",
    "telefone": "",
    "origem": "Subsystem Init",
    "admin": true
}

I can see the returned object is an instance of org.springframework.security.oauth2.provider.OAuth2Authentication

Magno C
  • 1,922
  • 4
  • 28
  • 53

1 Answers1

0

I found the system don't care about what I'm passing as a response.

@RequestMapping("/user/me")
public @ResponseBody MyCustomUser user(Principal principal) {


    MyCustomUser customUser = new MyCustomUser( this.userService.getUserByUsername( principal.getName() ) );

    return customUser;
} 

To take it back at client side:

    @RequestMapping(value = "/whoami", method = RequestMethod.GET, produces = "application/json")
    public @ResponseBody OAuth2Authentication whoami( Principal principal ) {

        OAuth2Authentication user = (OAuth2Authentication)principal;
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken)user.getUserAuthentication(); 

        Map<String, Object> details = ( Map<String, Object> ) authentication.getDetails();
        for ( Map.Entry<String, Object> entry : details.entrySet() ) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println("  > " + key + " : " + value.getClass().getName() );
        }

}

Can someone tell me why it came as LinkedHashMap instead MyCustomUser ?

Magno C
  • 1,922
  • 4
  • 28
  • 53