Using Google's OpenID Connect as part of a SSO - authentication

I'm developing a common auth service for several different web services. The general idea is that a user goes to one of these web services and clicks on a login button and gets redirected to my auth service. Once authenticated, the auth service redirects the user back to the original web service.
To begin with, the auth service will use Google's OpenID Connect service. One idea I had was that when a user was authenticated using Google I could pass around the resulting JWT to other services to use as an auth token. Google mentions this idea in their documentation (https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken):
One thing that makes ID tokens useful is that fact that you can pass them around different components of your app. This can be helpful because different components of your application may pass the ID token between them and use it as a lightweight authentication mechanism authenticating the app and the user.
Can anyone help me with the actual details on how this should work e.g. How do I handle log outs both on Google and from the auth service? There appeared to be some documentation on this in older OpenID Connect Session documents (-03) but it appears to have been removed.

You should not pass the ID Token that you receive to Google back to the app to use as an auth token. The ID Token will have an audience specific to your app, not the ultimate client.
If you just passed this back to clientA, then you would open it up to auth attacks where clientB could obtain an Google ID Token via your auth service and then use that token to gain access to user data in clientA.
A much better approach would be to mint your own ID Token and provide an audience designation for each app that uses your service.
Monitoring session state is not as straightforward. The easiest thing to do is for your service to wrap G+ sign-in libraries and interface with the session state api's.
https://developers.google.com/+/web/signin/session-state

Related

Who generates JWT when using Google OpenID Connect authnentication for my ASP.NET Core Web API app?

I am building an ASP.NET Core 6 Web API application for mobile clients (and maybe later SPA JS app). The application should have sign-in with Google option. I also want to add my own app's custom sign up and sign in options that would also be based on JWT authentication and not cookie.
I understand that for my custom sign in flow my app will generated JWT that will be sent to the client.
But I have few questions how that works when user signs-in with its Google account:
who's responsibility is to generate the JWT when user signs-in with its Google account? Is that responsibility of Google or mine application? I don't want Google to return JWT to the client in the cookie.
Then when client is authenticated with Google, and sends requests to my application, how can my application validate JWT token it gets?
When user signs in with Google for the first time, should I automatically register that user in my application (I am using Identity framework) by taking claim values (email) from the JWT? What is the general practice here?
I am trying to understand these processes and flows so sample code is not necessary (but I do welcome it).
Ad.1. Normally, in a larger system, you would have an authorization server (AS) that would handle user authentication and the issuance of tokens. Your clients would contact only the AS, and the AS will be able to provide the user with different forms of authentication: e.g., through your website's password or through Google. The AS is the single point of issuing tokens to your clients. It can issue tokens regardless of the authentication method used. So it then doesn't matter whether the user authenticated with Google or a password, the client will still get the same access token.
Ad.2. When the AS issues token to your client, then you don't have any problems validating that token. The client doesn't care if the user authenticated with Google or not, it's not relevant in this case.
If you decide to skip using an AS and let the client receive tokens directly from Google, then you can still verify them. An ID token is a JWT and can be easily validated with a JWT library using verification keys provided by Google. Access tokens returned by Google are opaque tokens (If I remember correctly), and you need to check whether Google exposes an endpoint to verify them.
Ad.3. That is the general practice. When the user authenticates with Google and you notice that you don't have that user's data in your system, then you take the information from Google's ID token and create a user entry in your system.

OAuth 2 authentication for both iframe and api

I'm integrating several web sites/services into my application. I use iframes (or webview for Vue Electron) for UI integration and I also use API to implement cross-communication between those services.
At the moment I have to go through OAuth 2 authentication twice for each service: once as part of natural authentication in iframe and another when I ask the user to give me access to this service (for api reasons).
Is there any way to streamline this process?
The state of the art response would be to modify your application completely.
You should have 1 SPA application and not iframe
This application would authenticate to get OAuth2 token
This application would then call the backend (access multiple backend, or access on api management layer that call backends).
Thing is, with this you can have 2 strategies :
give all permission (scope) at 1st authentication
give the smalled scope possible at 1st authentication, then when needed "reauthenticate" (in fact validate new scope) to get new access token
When an API want to call another API, you have also 3 strategies:
you simply use the same client token the API receive to the service your API call (no human interaction needed)
your API generate a token from a service account (using ROPC authentication scheme) or via a client credential scheme (the access token will be valid but usually not be bind to a real user), (no human interaction needed). (the API will be the client of the 2nd API)
your identity provider have an endpoint to transform access token : Your API can give the client access token, and authorization server will transform this with the client_id of your API. You send this token to 2ndAPI ( token will show subject of your UI application, but client ID will be the 1st API clientId) (no human interaction needed)
Now if you use IFrame with multiple sub-application on the same domain (the domain need to be exactly the same!), it is possible to share the same access token for instance via local storage. (security is not top notch)
You will probably need to authenticate with a bigger scope list sometime but it is your only option. You will simulate a single page application, but issue is that you will have potentially different client_id depending first application you authenticate to.
Edit: Multiple authorization server
From your comment, you have multiple authorization server. One strategy could be to ask user to authenticate, your application can then get an access_token and a refresh_token.
Depending on your authorization server, refresh_token can be used a lot / on a long period of time, so that if you store it somewhere, the next time the user visit your application, your application can silently get an access_token from this refresh token. Your application have then access to remove api without newer interaction from your user.
Of course, this means you have to save this token the most safely you can.
By using OpenID Connect you could combine authentication and authorization in a one step and get both an id_token to logon your user to your app as well as an access_token to access APIs in a single authentication response.

API oauth2 which grant type should I choose

I'm working on a personal project composed of an API and 4 clients (web, android, iOS, windows phone).
I'm using django-rest-framework and oauth2 toolkit on the API side and I wonder which grant_type would be more suitable in my situation.
I read somewhere that the implicit grant_type is appropriate for working with mobile clients.
I'm currently using the resource owner password credentials system.
My current workflow is:
The user creates an account on the API registration page (http://mysite/api/register) then gets redirected on the web client.
The user have to authenticate himself on the API from the web client (the secret and client ID are store in the web client). If the authentication is successful the access_token and refresh_token are both stored in the user session.
Each time the user want to access a page I verify if he is authenticated by requesting the API using his access_token. If the request fails, I retry with the refresh_token. If it's fails again I redirect the user on the auth page.
The user can use the API on a mobile client with the same account without extra manipulations (the secret and client ID are store in a secure location ex. share preferences or keychain)
I like this workflow, it's simple and convenient for the user: he registers once and can use all the clients and I get a perfect separation between the logic (API) and the UI (client). But I'm worried about the security of this system. I don't want to expose my users to threats. Do you guys have any thoughts, recommendations, suggestions?
You help in this matters would be very appreciated.
Thanks in advance!

How to authorize mobile apps with a third party by oauth BUT connect to my service, not the 3rd party

My app is architected as follows: I have a web service (running on GAE, not very relevant to this question) and the data that this service contains is made available through a website and through mobile and desktop apps.
Currently, the user authenticates to the website via Google ClientLogin and the apps authenticate/get authorized via GAE's built-in oauth provider. (OAuth is being used here mostly for authentication, my app doesn't actually use any external data via OAuth other than the user's unique ID and email address.)
What I'd like to do is expand the number of services that users can use to login. Because of the complicating factor of the apps, it seems I need OAuth. But I can't really properly conceptualize how this flow should go.
Lets take Facebook as an example. When a mobile app goes through the Facebook oauth flow and acquires an access token, this isn't enough - because its my service, not the app, that actually needs to talk to facebook to retrieve contact info and a unique user ID. This leads me to think that the OAuth process needs to happen in the context of my service, and not the mobile app. My service then becomes the consumer and Facebook the oauth providor, and the service holds on to the oauth access token, this happens when a user sets up their account for the first time.
If this is the correct approach, where does that leave authentication for the apps? What happens when the user already has an account and installs a fresh instance of a mobile app? I imagine also going through the oauth process, matching up credentials with the data already stored by my service, and then issuing my own "access token" to the app from the service, to authorize that instance of the app. This seems convoluted and hackish.
I'm sure I can't be the only person who is in effect "borrowing" the account system of a third party for a mobile app with a backend, but I really don't see what the proper way to do this is.
What am I not seeing and/or getting conceptually wrong?
A few colleagues and I once did a project quite similar in nature, back in university. We authenticated our users through either Facebook or Foursquare, using their respective OAuth APIs.
The native Android version of the app opened up a WebView with the OAuth provider's start page, which redirected back to our service after authentication. Then our service did a request for the OAuth token from the OAuth provider (Foursquare has some pretty simple instructions). When we got that token, we set up a session using cookies, which we could access from the app.
To validate sessions, we just checked whether the access token was still valid with the provider. We also used the respective providers' unique user IDs to distinguish users.
So yes, what worked for us is: Make the app authenticate & authorise your service, not the app itself.

Which is the better way to implement authentication using login/password AND other social networks?

I'm gonna try to explain my problem :
I'd like to allow users to connect to my api via their own accounts (login/password) or via a social network (Facebook at first).
Then, I would allow any application to use my api, with the user authenticated.
My first thought when to auth the user via his/her login/password and return a token used as the session for the next requests.
But OAuth would seems to be the better implementations, except I don't know how to do this :
One of my applications will have to connect via login/password, like twitter web (I have to implement an login/password auth somewhere if I wan't my user to login :p)
Will I also have to register my applications to the oauth system (did twitter added their web app to their oauth ?)
How to merge the auth via others social networks. Concretely, the user will have to OAuth to my api that will auth to the social network.
I'm a bit lost on how to do this, if someone could help me, I would really appreciate !
Thanks
Update 1:
Flickr and Lastfm seems to not use OAuth but an alternative auth system that looks like this :
The user is redirected to Flickr/Lastfm
The user auth himself and accept to use the application
Flickr/Lastfm return to the Callback url with a temporary frob (for flickr) or token (for lastfm)
The app must call the provider with the temporary frob/token (among with the api_key and the api_sig, as always) and get in return the session token to use for the next calls.
Update 2:
In fact, StackApps is the concrete case of my problem : you can login through their login/password system OR openId, and you can use their API.
OAuth is only needed to make others use your API on other services, i.e. authorize services to use your API without users of the intermediary service explicitly having to log in into your service by giving user's login credentials to a third party.
What I think you need is OpenID, the cross-application authentication mechanism. You just need to implement an OpenID client, accepting third-party OpenIDs to authenticate users, to subsequently identify them, when they use your service's API. This would have to be supplemented with a normal 'local' user authentication mechanism (i.e. login/password entry page)
You will need OAuth to provide an ability to use your API on other sites, though.