I’m currently learning about OAuth2. I went through two different courses and none of them answered how OAuth should be implemented in microservices world.
Let’s say there is an app for uploading photos after user registration. I would let users to log in to the app with Facebook and Google. App will be available via:
- iOS app
- Android app
- browser (Single Angular Page Application)
And in the backend there are many Spring Boot/Node.js/whatever microservices exposing REST API requiring authorization. Because I would like to let users to register with standard registration form, I guess I need my own authorization server as well.
In such scenario my understanding of OAuth roles in the process is:
- resource owner is an app user
- client is mobile app or Angular app
- authorization server is Google server or Facebook server or our internal server
- resource server(s) are microservices exposing API – am I right?
Let’s say there is a user trying to log in to my app with Facebook via browser. He went through the OAuth process and the client (iOS app) finally get Access Token. And in this point questions arise.
-
Are my all above assumptions correct?
-
Should Client keep the Access Token in it’s memory and pass it to each API request? I guess not. It’s enough to close the browser to lose session. If not – what should Client use to authorize on API calls?
-
If backend service exposing API receives request with Access Token, should it ask external Authorization Server if it’s valid whenever it receives a request? Sounds like an overkill, so I guess not. If not – how should it verify if given Access Token is valid?
-
AFAIK it’s not recommended to use ID token to authorize API requests. Access Token has been designed for that. If so, how backend service should identify who actually is the Identity the request has been made in behalf of? Should it call
/userinfo
endpoint on Authorization Server whenever it receives a request? Again, sounds like an overkill, so I guess not. If not – how service should know in behalf of who given request has been done?
Hope my problems and questions make sense and are understandable.
Best regards!
3
Answers
Your understanding of OAuth2 actors is correct and that’s a good starting point.
Clients should use certified OpenID client libs to handle OAuth2 flows and requests authorization (this should solve your questions about tokens handling on client).
As authorization-server, use an OIDC implementation capable of identity federation. You might pick an "on premise" solution like Keycloak or a SaaS one like Auth0, Amazon Cognito and many others. All those have "social login" feature which enable to easily login with Facebook, Google and quite a few others. This authorization-server you choose will be the only one for your clients and resource-servers (it will proxy Google and Facebook authorization-servers).
For validation, you can choose to use JWT access-tokens which can be self validated (content is signed and public signing key can be retrieved from authorization-server once for all tokens).
Last, access-tokens have a
sub
(subject) claim, which is a unique identifier. Also, you should be able to enrich access-tokens with any private claim you need for access-control decision. How to add such claims depends on the authorization-server you choose and how to use it for access control decision depends on your resource-server security framework.You can have a look at my tutorials for advanced access control in Spring resource-servers based on private claims. In this other project, I defined a Keycloak mapper to add private claims to access-tokens. I already defined private claims with Auth0 but haven’t public sources.
If I’ve read properly (- not too tired), then in relation to "am I right?", yes – your assumptions sound correct.
OIDC (& OAuth underneath) are I.M.H.O. (both) a complex subject.
Yes, the client should pass the access (/bearer) token (via the HTTP ‘Authorization’ header) for/with each (& every) resource server/endpoint call (- where authorisation is required).
You can check a few facets to see if the token is valid – but some languages/frameworks/packages have a provision to simplify the validation process/steps for you (- e.g. C#/.NET has a NuGet package that provides this).
Most OPs (OIDC Providers) can be configured to return both the access-token & id(entity)-token as part of the authorisation call (- e.g. as part of the ‘authorization code’ flow). Therefore, you shouldn’t necessarily need to actively/separately call the (OIDC) ‘userinfo’ endpoint.
For added security, try to also use ‘pixie’/PKCE (Proof Key for Code Exchange).
(Hope this helps clarify some points/uncertainty.)
Yes, but probably scenarios are different for mobile application and web browsers. I am not mobile dev but as I correctly understand you can obtain and store tokens securely on mobile app, but for SSO you should create user session based on id token (obtained via OIDC) that should be validated on backend only during login (maybe the same is recommended for mobile apps).
In general crucial point is to understand difference between OAuth 2.0 and OIDC. Access token for OAuth 2.0 is delegated by user for application, or i.e. for client credential grant type is obtained in service context,not user so in those scenarios it should be stored on backend side. For regular user communication with rest api user session is preferred, OAuth 2.0 and access token is designed to retrieve some information from resource server in context of application, where user delegate access.
Access token uses in most cases JWT and JWS implementation where signature is used (asymmetric cryptography) so it can be verified with raw public key(without communication to authorisation server) or JWKS uri(with one request to authorisation server and some caching mechanism). Additionally you should validate i.e. exp, aud etc. following OAuth 2.0 standard.
OIDC is build on top of OAuth 2.0 for user authentication, so ID token is token that contains user information and should be used to create internal application session during user login. Access token should be used to authorization for resource server i.e. you have web app that is responsible for sending emails for birthday reminders for your friends. You allow SSO login with Facebook, so user can login with SSO, internal session is created and used for user authentication with your app backend services. Access token is used only when app needs to save list of your friends and their birthday date, so you delegate access to backend client that can communicate with Facebook resource server.
Useful links to understand OAuth 2.0 as delegation framework(protocol) and OIDC as authentication protocol: https://oauth.net/specs/