Spring OAuth (OAuth2): How can I get the client credentials in a Spring MVC controller?
Asked Answered
M

5

21

In this snippet:

@RequestMapping(method = GET)
public List<Place> read(Principal principal) {
  principal.getName(); 
}

principal.getName() gives me the user identification but I need a way to receive the client credentials (client => the app who is using my API). How can I do this?

Maidy answered 17/9, 2012 at 17:8 Comment(0)
M
16

I found a reasonable solution based on @luke-taylor answer.

@RequestMapping(method = GET)
public List<Place> read(OAuth2Authentication auth) {
  auth.getOAuth2Request().getClientId()
}
Maidy answered 26/9, 2012 at 19:12 Comment(2)
This returned me the Principal user and not the client id applicationDumpling
Updated version : auth.getOAuth2Request().getClientId()Shawnee
G
24

The client identity is available from the Authentication object which you can either cast the principal to, or get directly from the thread-local security context. Something like

Authentication a = SecurityContextHolder.getContext().getAuthentication();

String clientId = ((OAuth2Authentication) a).getAuthorizationRequest().getClientId();

If you don't want to put that code directly into your controller, you can implement a separate context accessor as described in this answer and inject that into it instead.

Grantinaid answered 18/9, 2012 at 12:38 Comment(2)
nice answer, except the post date is little old. The spring boot 1.3.3 is using getOAuth2Request() instead of getAuthorizationRequest()Christen
How about client secret?Graces
M
16

I found a reasonable solution based on @luke-taylor answer.

@RequestMapping(method = GET)
public List<Place> read(OAuth2Authentication auth) {
  auth.getOAuth2Request().getClientId()
}
Maidy answered 26/9, 2012 at 19:12 Comment(2)
This returned me the Principal user and not the client id applicationDumpling
Updated version : auth.getOAuth2Request().getClientId()Shawnee
O
5

Fleshing out the HandlerMethodArgumentResolver option a bit more. In order to support the following:

@RequestMapping(
    value = WEB_HOOKS, 
    method = RequestMethod.GET, 
    produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public List<SomeDTO> getThoseDTOs(@CurrentClientId String clientId) 
{
    // Do something with clientId - it will be null if there was no authentication
}

We'll need the HandlerMethodArgumentResolver registered with our Application Context (for me this was inside a WebMvcConfigurerAdapter). My HandlerMethodArgumentResolver looks like this:

public class OAuth2ClientIdArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterAnnotation(CurrentClientId.class) != null
                && parameter.getParameterType().equals(String.class);
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer, 
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) 
        throws Exception 
    {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication == null) {
            return null;
        }
        String clientId = null;

        if (authentication.getClass().isAssignableFrom(OAuth2Authentication.class)) {
            clientId = ((OAuth2Authentication) authentication).getOAuth2Request().getClientId();
        }

        return clientId;
    }

}

And the @interface definition:

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentClientId {

}
Oversell answered 2/2, 2015 at 18:57 Comment(0)
P
1

It's also possible to obtain declaring a org.springframework.security.oauth2.jwt.Jwt object with org.springframework.security.core.annotation.AuthenticationPrincipal annotation.

@GetMapping
public String showClientId(@AuthenticationPrincipal Jwt principal) {
    return principal.getClaimAsString("clientId");
}
Plasmosome answered 4/8, 2020 at 18:3 Comment(0)
R
0

With the deprecation of spring-oauth some of the other answers no longer work. I used the following to get the clientId in a AuthenticationSuccessHandler with spring-security 5:

@Autowired
public OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository

protected String getClientId(final Authentication authentication, HttpServletRequest request) {
    OAuth2AuthenticationToken auth = (OAuth2AuthenticationToken) authentication;
    OAuth2AuthorizedClient client = oAuth2AuthorizedClientRepository.loadAuthorizedClient(auth.getAuthorizedClientRegistrationId(), auth, request);
    String clientId = client.getClientRegistration().getClientId();
    return clientId;
}
Regenerator answered 11/11, 2021 at 14:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.