I'm developing a microservice in C++ (for low latency reasons), and I'm beginning to dive into OpenID and Keycloak. Developing in C++ means I've almost no library support for OpenID, but I've (hopefully) the all the low level details working (like proper JWT verification). I've to do all the communication flows and redirects myself.
So much as a background. Keep that in mind because I need to know and implement details which usually a library will hide for a developer.
There are three parties in my application:
A web client W
Microserice A
Microservice B
General communication between those three: The web client W could be either a frontend UI or a mobile device using just the API as a service without having any sort of frontend. W connects to microservice A to manipulate and consume data from it. Microservice A exchanges data with microservice B and vice versa. W does not need to know about B.
So far I thought of the following architecture:
For the Web Client to Microservice A communication I'd use dedicated users and clients with access type "Public" in Keycloak to allow user/pw logins
For the Microservice A to Microservice B communication I'd use Access Type Bearer because they never initiate any login
Please advise if you think that does not sound right. My actual question is however what kind of login flow(s) is required and which step there are in between which I may miss:
Is it ok to have an endpoint for the login on microservice A https://servicea.local/login which redirects the requests of the web client to OpenID / Keycloak. E.g. the web client sends username, password, client id and grant typeto the OpenID token request endpoint http://127.0.0.1:8080/auth/realms/somerealm/protocol/openid-connect/token ?
Should the client take the token and add it to all subsequent calls as authorization token?
Should the Microservice implement a callback to retrieve the authorization information?
Should the flow instead be changed for the client to service communication to provide an access code to he service which it exchanges with an access token?
I would aim for an architecture where the role of your C++ APIs is just to verify tokens and serve data.
The client side is a separate solution though, requiring its own code for logging in + dealing with authorization codes and getting tokens. This should not involve your API - so to answer your questions:
Not recommended
Yes
No
No
These days all logins should occur via the system browser, whether you are writing any of these. This client side code is probably not C++ and often requires more work than that to build the API:
Web UI
Mobile UI
Console / Desktop App
If it helps my blog has a lot of write ups and code samples about these flows. In the following post, notice that the API is not called until step 13, once all login processing has been completed by the web client.
OAuth Message Workflow
Authentication (delegating to Keycloak) and then getting Token should be done by your UI by directly contacting keycloak and that token should be passed on from UI to A to B
Here are the OIDC endpoints that keycloak provides
https://www.keycloak.org/docs/latest/server_admin/index.html#keycloak-server-oidc-uri-endpoints
Related
I'm new to security domain, and recently I have learned about Oauth2.0/OpenID connect and JWT tokens. I have an existing REST based web application where I need to implement security.
Server
Application A: Spring boot back-end application sever, with some RestEndpoints exposed connected with Mysql database.
Front End
Application B: Spring boot Web Applicaiton which have some JSP pages for login and some other template features(Also connected with same Mysql database used by back-end server).
Application C: Inside application B we have an Iframe in which Angular app is running, angular app calls the back-end server and show data.
Also in future we want to use SSO for our application as well.
Current Security
At the moment we don't have any security on back-end server (i.e We can simply call RestEnd points without any authentication), Application B has basic login security implemented via spring security. User logins on application B and then he/she can use application C (Angular) as well. User session is managed at Application B, when session expires users forced to logout.
Oauth2 Authorization
What we are trying to acheive is make the server (Application A) as Oauth2Resource server and Oauth2Authorization server. Application B (JSP front end) remove database connection from it as well as the login controller, application B will call oauth2 server for authorizing user with "password" flow, when application B will receive access_token and refresh_token it will then somehow pass it to Iframe (angular app) to store these tokens inside cookie and on every subsequent request to server angular will add access token to it.
I've read articles about that Oauth2.0 have deprecated the use of "Implicit Flow", and they prefer to use the "Authorization Code Flow". I am having a very hard time to understand how this flow can be used for single page applications(SPA like angular). Also where to store the access_token and refresh_token if I use the implcit flow? I'm aware that storing both tokens in cookies is not a good practice.
Also how to manage user session now? what I have gathered so far is that, on requesting resource server with Bearer access token, when we get unauthorized response, we'll then request for new access token with help of refresh token, but in case when refresh_token is also expired I will force user to login screen. Is this right approach?
Sorry for the long context, any help will be highly appreciated. Thanks
A couple of recommendations:
Use a low cost cloud Authorization Server, eg Azure or AWS
Focus on building great UIs and APIs, which is not easy
In terms of flows, use the Authorization Code Flow (PKCE) and the OIDC Client library to manage SPA security.
A good starting point might be my First Tutorial to understand how to get integrated. Generally:
SPAs use short lived access tokens and should store them in memory
SPAs traditionally do not use refresh tokens directly
Feel free to post back follow up questions and I can point you to additional resources. You should aim to avoid running the SPA in an iframe by the way - see my other answer.
Is it recommended or good practice to protect a Web API directly with Open ID Connect or not?
The setup:
Mobile App
Authorization Server (ADFS 4.0)
Web API (ASP.NET Core)
Currently I do the normal OAuth2 "Authorization Code Flow", and then pass the access_code to my Web API in the HTTP Header as "Authorization: Bearer ".
In ASP.NET core I just do the usual
services.AddAuthentication(...).AddJwtBearer(...)
Works fine.
But everyone talks about OAuth2 beeing only "pseudo-authentication" with certain flaws. I want my Users to be a properly authenticated before using my Web API. So it seems like Open ID Connect should be the way to go, aka "real authentication".
But does it actually work to "consume" Open ID Connect authentication in an ASP.NET Core Web API? And if yes, how? And is it good practice? All samples seem to be about Web Sites, not Web APIs.
There is an extension method
services.AddAuthentication(...).AddOpenIdConnect()
But here Implement OpenID connect Authetication in asp.net WEB API they state that "this component is designed for user interactive clients".
What i also don't understand, what would I do with the "id_token" I get from Open ID connect.
Currently i just pass the "access_token" as Bearer.
How do i consume the id_token?
Some clarifications:
The API does not act on behalf of a user (access to company data).
The API already has access to the "data". It does not require any auth workflows for itself nor does it need to pass the users credentials along.
The API needs to know "WHO" the user is, and it has to be done in an modern and good way
That's why I was thinking of OICD with its "real auth" (VS Oauth2-only which is "pseudo").
I basically cannot wrap my head around how the stuff returned from OICD (id_token) will be passed to my Web API.
OIDC is an OAuth workflow. It merely extends OAuth; it is not a replacement for it. APIs are typically authorized either by token or client secret. The difference is simply whether it's acting on behalf of a specific user or not. For example, something like the Facebook API has both workflows for its API, you generally operate with Facebook's API as a client app using the app id and client secret for your app, or you can do user-specific things like create a post on the user's wall given an authorization token.
That authorization token almost invariably comes from an OAuth workflow. Given your stated setup, your mobile app would handle this to get an auth token for the user from your ADFS server. Your API, meanwhile, would actually probably do both. It would communicate both using an assigned client secret and a user auth token, if the mobile app provides it with one.
I have a scenario in which a mobile (native) app is requiring data from a long running task. The task is a continuesly running on the users behalf, and we have decided to move it to a backend service. To execute the task, the backend service must regularly fetch data from an API that is OAuth2 protected.
Our dilemma is that we are not sure how to provide the backend service with a set of access tokens to access the data API. Our mobile app uses the OAuth2 Authorization Grant flow with PKCS to get its own access token, refresh token and id-token (we use OpenID Connect). But how do we provide our backend service with a set of tokens? As the backend is continuesly running (also in absence of the mobile native app) we would like to provide it with its own set of access/refresh tokens.
There seem to be several solutions:
Proxy all mobile app communication to external APIs via the backend, make the client a private client, use the authorization code flow, and setup custom login sessions between the native app and our backend. To me this means more running backend infrastructure, and implementing session management including session refresh, etc. which is like re-implementing the OpenId flows on my own servers...
Using OpenID hybrid flow, providing both an access token as well as an authorization code to be shared with the backend. However, this seems to be directed at (in-browser) web-apps, not so much native mobile apps as it based on the implicit flow and as such less secure.
Doing the authorization code flow twice on the mobile app (optionally second time with prompt=none to suppress user interaction), keeping one code for the app, forwarding the second to the backend. Then both backend and app can exchange their own codes for access tokens. This feels a bit like a hack as the backend should be a private client, not a public client. It is the approach that Google seems to advertise though in CrossClientAuth
Performing impersonation by sending the id-token to the backend which then exchanges that id-token for its own set of access/refresh tokens. Microsoft does this through the jwt-bearer grant in its "on-behalf-of" scenarios. Moreover, the token-exchange RFC seems to cover the same use-case. However, in this scenario the id-token is indirectly used as access credential, not just as a bag of claims about the user identity, which is odd in my view as access should be controlled through access tokens, is it not? Moreover, not all services should be allowed to impersonate, so I suppose this comes with additional configuration complexity.
To me it feels that I'm overlooking something, this must be a problem others have too and must have been solved before... What would be best practice in my situation?
I'm trying to understand how to best apply the OAuth 2.0 grant types to a microservice architecture I am working on. Here's the situatation...
I have a Single-Page Application/Mobile App acting as a client running in a web browser (browser acting as the user agent) or mobile phone. I use the Implicit Grant defined in RFC 6749, section 4.1 to authenticate a user and acquire an access token that the app uses to access some externally exposed API.
The architecture I am dealing with is a collection of microservices that call on one another. For example, consider an externally exposed API serviceA and internal APIs serviceB and serviceC. Let's say serviceA depends on serviceB which subsequently depends on serviceC (A --> B --> C).
My question is, what is the typical authorization flow for this situation? Is it standard to use Implicit Grant for the SPA to acquire an access token and then use the Client Credentials Grant defined in RFC 6749, section 4.4 to acquire an access token for the machine to machine interaction between serviceB and serviceC?
For your single page application, use the Implicit grant, which is designed for browser applications - they cannot hold any secrets and with the Implicit grant, the tokens stay in the browser (because it's in the hash part of the redirect URL).
The mobile app, take a look at the OAuth 2.0 for Native Apps, it recommends the use of the Auth code grant. It also describes implementation details for common platforms and security considerations.
There is a new grant described in the OAuth 2.0 Token Exchange RFC that would suit your needs for chained calls between services:
... An OAuth resource server, for example, might assume
the role of the client during token exchange in order to trade an
access token, which it received in a protected resource request, for
a new token that is appropriate to include in a call to a backend
service. The new token might be an access token that is more
narrowly scoped for the downstream service or it could be an entirely
different kind of token.
But I don't know whether Auth0 supports it. If it doesn't, I would probably pass the original access token from serviceA to serviceB and serviceC. The internal services could be secured at the network level too (e.g. they could called just from other services).
If serviceB and serviceC are internal and will never be called from an external client then the Client Credentials Grant would be a good candidate. As the client is also a resource server too.
You could also look at passing the same bearer token between services, providing the SPA (which requests the token initially) obtains consent for all scopes which may be used by the other services and the "audience" of the token must allow for all the possible resource servers (services).
I don't think either are best practice and there are tradeoffs with both ways.
I would honestly recommend for each backend service to implement the Authorization Grant. That is have an endpoint exposing the redirect to your provider. Then for each frontend app go to that endpoint to trigger the OAuth flow. After the flow has been completed handle the Authorization part in the callback url and return a token which will be stored on the frontend somewhere.
Hope this helps.
Currently I am implementing an Ionic application that the front-end is on the mobile devices and the back-end is on the server. (So there is a connection latency between the device and the server) And my application is using the Google services (like Gmail, calendar, etc) by connecting to the Google API.
Currently the architecture is:
Device <==> Server <==> Google API
This is using the OAuth 2.0 server-side authentication. It works but the connection latency is way too long and feels like going back to the time when we have the dial-up internet connection.
I tried to use the OAuth 2.0 client-side authentication, which is:
Device <==> Google API
This is faster but it has 2 problems:
Even though Ionic packaged the front-end code into an application, I still have concerns that the rule "Everything in the front-end is visible to everyone" stays. (Did not find an evidence to prove or disapprove this hypothesis)
Google API OAuth 2.0 only issues flows to the client-side authentication, and flows expire very often, I don't want the user to grant the permission again and again.
So, I was wondering if it is possible to do the following:
Use the server-side authentication to store keys/credentials (I'm using Django as the back-end, which is Python) and the front-end gets keys/credentials from the server and proceed Google service using JavaScript codes.
I know this is late to the party, but I'm going through this now. I think there are 2 ways to set this up, but neither are perfect.
Use server-side flow to authorize all the scopes you'll need on either the server or the client. When the token is obtained, pass it to your client. The down side is that the client now has a token that has access to more APIs than needed.
Create seperate authorization flows for both the client and server. This would mean the user has 2 authorization prompts, which is no good. The good thing about this approach is you could ensure the client has limited scopes, but the server could still handle the larger tasks (moving Drive files, sending emails, etc.)
In my case, the client would just need read access to the Contacts API, whereas the server needs full Drive access.
If anyone finds a combination approach, where only 1 authorization is needed, but the client and server have seperate scopes, that'd be the ideal situation.