OAuth2AuthenticationToken not been recognized in g

2019-08-21 01:57发布

问题:

I have a native android client with OAuth2 authentication to my JHipster monolithic app. It worked properly with the JHipster version 5.7.2, but now I am using version 6.0.1 and I am not been able to get the current user by using getAccount(Principal principal) method in AccountResource class. the object sent by keycloak is not an instance of OAuth2AuthenticationToken class, so I am getting a Exception "User could not be found"

In the previous version I used to get a OAuth2Authentication object that worked fine. The object I used to receive was like this:

{
  "storedRequest": {
    "resourceIds": [

    ],
    "authorities": [

    ],
    "approved": true,
    "responseTypes": [

    ],
    "extensions": {

    },
    "clientId": "web_app",
    "scope": [

    ],
    "requestParameters": {

    }
  },
  "userAuthentication": {
    "principal": "Admin Administrator",
    "credentials": "N/A",
    "authorities": [
      {
        "role": "ROLE_USER"
      }
    ],
    "details": {
      "sub": "f348bbbb-9441-4543-9940-9da31e50d877",
      "email_verified": true,
      "roles": [
        "offline_access",
        "ROLE_ADMIN",
        "uma_authorization"
      ],
      "name": "Admin Administrator",
      "preferred_username": "admin",
      "given_name": "Admin",
      "family_name": "Administrator",
      "email": "admin@localhost"
    },
    "authenticated": true
  },
  "authorities": [
    {
      "role": "ROLE_USER"
    }
  ],
  "details": {
    "remoteAddress": "192.168.0.14",
    "tokenValue": "eyJhbGciOiJ...",
    "tokenType": "Bearer",
    "display": "remoteAddress\u003d192.168.0.14, tokenType\u003dBearertokenValue\u003d\u003cTOKEN\u003e"
  },
  "authenticated": true
}

Here the object I am receiving now in the version 6.0.1:

  "token": {
    "headers": {
      "kid": "w4uKMWW49GwLl-gakp9tAo6su7nAdddpo9Ul1pYABJo",
      "typ": "JWT",
      "alg": "RS256"
    },
    "claims": {
      "sub": "f348bbbb-9441-4543-9940-9da31e50d877",
      "resource_access": {
        "web_app": {
          "roles": [
            "ROLE_USER",
            "ROLE_ADMIN"
          ]
        },
        "account": {
          "roles": [
            "manage-account",
            "manage-account-links",
            "view-profile"
          ]
        }
      },
      "email_verified": true,
      "allowed-origins": [
        "*"
      ],
      "iss": "http://192.168.0.12:9080/auth/realms/jhipster",
      "typ": "Bearer",
      "preferred_username": "admin",
      "given_name": "Admin",
      "aud": [
        "web_app",
        "account"
      ],
      "acr": "0",
      "nbf": {
        "seconds": 0,
        "nanos": 0
      },
      "realm_access": {
        "roles": [
          "offline_access",
          "ROLE_ADMIN",
          "uma_authorization"
        ]
      },
      "azp": "android_app",
      "auth_time": 1559622495,
      "scope": "openid profile email jhipster",
      "name": "Admin Administrator",
      "exp": {
        "seconds": 1559622877,
        "nanos": 0
      },
      "session_state": "6c756fb9-c335-4a23-9c50-ed5adeb42456",
      "iat": {
        "seconds": 1559622577,
        "nanos": 0
      },
      "family_name": "Administrator",
      "jti": "6fe0962c-18c1-471e-b4c0-ad3afda12b46",
      "email": "admin@localhost"
    },
    "tokenValue": "eyJhbG...",
    "issuedAt": {
      "seconds": 1559622577,
      "nanos": 0
    },
    "expiresAt": {
      "seconds": 1559622877,
      "nanos": 0
    }
  },
  "authorities": [
    {
      "role": "SCOPE_openid"
    },
    {
      "role": "SCOPE_profile"
    },
    {
      "role": "SCOPE_email"
    },
    {
      "role": "SCOPE_jhipster"
    }
  ],
  "details": {
    "remoteAddress": "192.168.0.14"
  },
  "authenticated": true
}

I expect the Principal object received to be an instance of OAuth2AuthenticationToken. Any Suggestion?

回答1:

Well, I realized that the object I was getting was a JwtAuthenticationToken so I made some modifications to the getAccount() method to do the trick when receving this type of token. I also add a new parameters option for the getUserFromAuthentication() when receiving JwtAuthenticationToken.

@GetMapping("/account")
    @SuppressWarnings("unchecked")
    public UserDTO getAccount(Principal principal) {
        if (principal instanceof OAuth2AuthenticationToken) {
            return userService.getUserFromAuthentication((OAuth2AuthenticationToken) principal);
        } else if (principal instanceof JwtAuthenticationToken) {
            return userService.getUserFromAuthentication((JwtAuthenticationToken) principal);
        } else {
            throw new AccountResourceException("User could not be found");
        }
    }
public UserDTO getUserFromAuthentication(JwtAuthenticationToken principal) {
        Map<String, Object> attributes = principal.getToken().getClaims();
        User user = getUser(attributes);
        Map<String, Object> resourceAccess = (Map<String, Object>) principal.getToken().getClaims().get("resource_access");
        JSONObject webApp = (JSONObject) resourceAccess.get("web_app");
        JSONArray roles = (JSONArray) webApp.get("roles");
        user.setAuthorities(roles.stream().map(authority -> {
            Authority auth = new Authority();
            auth.setName(authority.toString());
            return auth;
        }).collect(Collectors.toSet()));
        return new UserDTO(syncUserWithIdP(attributes, user));

    }