Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security oauth2 - getting custom data from OAuth2 principal

I have a site that uses Spring security and has users (username & password) and standard form authentication. I allow users to generate a client Id and client secret linked to their account for use with an OAuth2 secured rest API.

I use a separate client id & client secret for the API and not username and password so the user can change their password etc without breaking the API credentials, set specific scopes, disable API access etc.

I use spring-security-oauth2 (provider) to secure the rest API and I have allowed a client credentials flow. I have setup client authentication for the api so that client id and secret are checked.

From a separate application I use the client id and client secret to retreive an access token and start to use it with the api. For the most part I use simple @PreAuthorize expressions typically based on client roles and scope and these appear to work correctly.

All above appears to work fine

However... I have a few API endpoints now however where I need to implement some more complex rules based on some details from the underlying user - in this case the user that generated the client id and secret.

As a simple example consider a messaging application where I have an endpoint that allows users to post a new "message" of a specific type that can vary. I have a table of allowed recipients for each user and each type and I want to check that the recipients of the posted message match the allowed recipient for the type. (User allowed recipients data is typically not large, and rarely changes so I'm happy to store a copy of it when generating an access token)

I get the principal at these endpoints and I see it is an instance of OAuth2Authentication containing:

  • userAuthentication - null - This seems expectable for client credentials flow.
  • clientAuthentication is populated and authorizationParameters contains the grant type and client_id

I suppose I could use the client id from clientAuthentication.authorizationParameters to lookup the user and the details I require, but that would be a few queries each api call which doesn't seem to make sense.

I would guess there's a nice place/way in Spring OAuth2 libs that while granting the access token that I could add some extra details so that later I could get them from the OAuth2Authentication (principal) object (or something that extends it?)

Alternatively is there a better approach entirely to such issue?

Thx!

like image 782
Mark Doyle Avatar asked Apr 23 '13 16:04

Mark Doyle


People also ask

Is Spring Security OAuth2 Autoconfigure deprecated?

Spring Security OAuth2 project is currently deprecated and Spring Security team has decided to no longer provide support for authorization servers.

What is SecurityContextHolder getContext () getAuthentication ()?

The HttpServletRequest.getUserPrincipal() will return the result of SecurityContextHolder.getContext().getAuthentication() . This means it is an Authentication which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication.

Is oauth2resttemplate deprecated?

Deprecated. See the OAuth 2.0 Migration Guide for Spring Security 5. Rest template that is able to make OAuth2-authenticated REST requests with the credentials of the provided resource.


2 Answers

Why you are not using Scopes which can be defined in client details and then use ScopeVoter to validate is this token have proper scope to access this resource or not.

please check my demo for more details

https://github.com/bassemZohdy/Spring_REST_OAuth_Demo

Update 1: I did not reply to part 2 of your question "getting custom data from OAuth2 principal" you can add rest service on your Authorization server which is be accessed using OAuth token to give you required information about this token user, so you do not have to care about "OAuth2 principal" you are dealing with Authorization server as resource server too.

like image 122
Bassem Reda Zohdy Avatar answered Oct 15 '22 06:10

Bassem Reda Zohdy


In my opinion the right approach here would be to use the oauth2 "password" flow instead of client-credentials. you can create a general client-id and client-secret and give them to all of your users. each user can than request his own token using those client details and his own username and password. This way, each token would be connected to a UserDetails object which will solve your problem. You can see how this done here : https://labs.hybris.com/2012/06/18/trying-out-oauth2-via-curl/

like image 44
achiash Avatar answered Oct 15 '22 06:10

achiash