My question is pretty straightforward but I am pretty sure it's just a lack of understanding on my part.
Background:
I have a prototype native android app as well as an asp.net Web API and I want to implement OAuthorization so that users can login through google+, Facebook, or Twitter.
Question:
What is the design pattern for this feature? I'm confused as to whether I implement OAuthorization through the mobile app or through the web API. It's probably a combination of both. I've read many blogs and tutorials but they fall short in helping me understand how these two aspects (app and web API) of my project would work together.
Thanks
In OAuth there are these players:
the Resources (for example your gmail contacts) this is not a player itself
the Owner of the resources (you're the owner of your gmail contacts)
The Authorization Server (where you login to gmail)
The Resource Server (gmail, which has the contacts).
The Client: an application which want to use the resources
Note that, in most occcasions, the resource server and the authorization server are the same server
OAuth allows you (the Owner of the resources: your gmail contatcs) to authorize a client (a third party app) to access the Resources (your gmail contacts) from the Resource server (gmail itself) on your behalf.
To do so, the typical flow is: you open the thrid party app (the client), and, when it needs to access your resource (the gmail contacts), it redirects you to the authorization server (gmail) and, apart form log in, if you wasn't logged in, the authorization server (gmail) informs you that your app (the client) is trying to access a resource (the contacts), so that you can approve or deny it.
If you approve it, gmail sends your application (throug an URL) a token which can be exchanged for a "bearer token". So, your app exchanges it, and receives the berare token, which can be presented to the resource server (gmail) to access the resource (contacts). From that moment on, the client (the third party application) will present the bearer token to the resource server and it will give it access to the resource (the contacts).
So, OAuth itself is not the best option for authentication. You can use it to authenticate by asking permission to get the basic profile info (name, perhaps email), and once you have access to that info you know who the user is. However, this simplistic implementation of Auth ad authentication server is not safe, so what you'll really use is OpenID, which is much safer. The flow is similar to he exaplined above, but it's standardized for different providers and safer.
The question is that you should use OpenID providers to delegate the authentication.
To see how to work with OAuth authentication, read this: Logging In Using External Sites in an ASP.NET Web Pages (Razor) Site and this: Code! MVC 5 App with Facebook, Twitter, LinkedIn and Google OAuth2 Sign-on
One option to use OpenID is dotnetopenauth.
NOTE: if you use OAuth, you need to register your application on the provider (Google, facebook...) so that you can use it. The OAuth authorization server must have a pre-configured list of clients (applications) with some configuration (for example the callback url, and client id and password) which will allow this clients (applications) to ask for permission to use them on behalf of the user (resource owner).
NOTE: you application can use OAuth to authorize itself, i.e. generate and check tokens, using OWIN middleware.
Once you understand the inner working of OAuth and OpenID, you can use any of the available libraries for different languages: from the openid.net libraries list.
Related
I created an Android app that uses AppAuth to authenticate with Google OAuth. In the Google Cloud Platform Console, I created an Android OAuth 2.0 client ID for my app and provided the app package name and signing-certificate fingerprint. Everything is working fine.
I wanted to verify that only my app can use that client ID. So I created a second app with a different package name and signed it with a different signing certificate. Using that same client ID, I'm still able to authenticate with Google and access APIs. I didn't think this should be the case. I was looking at the source code for AppAuth and it doesn't look like it ever uses the app signing or package name during the authentication flow. It uses PKCE of course, but I expected more to be happening.
So if I can steal my own client ID with little effort, what's to stop someone else from extracting my client ID from my APK and using it for authentication? The custom scheme I'm using for redirect URI is easy to figure out based on my package name. So the rouge app could configure AppAuth to use a similar redirect URI and capture the authorization result. And since PKCE is only used to verify the authorization request and code exchange come from the same place, a rouge app would be doing both so there's no real protection there either.
I could switch the client ID type to Web or Other, but that will require me to use a client secret, which is just as insecure if you embed it in an app.
Am I missing something or is Google OAuth working exactly as it was intended?
For client side Google OAuth 2, your Client ID does not really matter. The client performs the OAuth flow and the client receives the OAuth token. The magic is that the client must authorize Google. Anyone can steal your Client ID but they cannot do anything with it. As part of the OAuth lifecyle you should be validating OAuth tokens. Your backends should NOT be blindly accepting anything from a client - or anywhere not under your absolute control.
Your Client ID is not a secret and you can put that in the clear in your code.
It is the Client Secret which must remain secret. The Client Secret is not involved in client side authentication. The Client Secret is used on your backend servers.
I think that you are confusing the process. When the client application (your app, a web browser, etc.) authenticates with Google Accounts, your app is not being authorized. The client is being authorized. The client should use good judgement on which websites they visit (or apps) and use their Google logins with. The only thing that a client can do with their token is access their own data (Google Drive, Gmail, etc.). If your backend servers are accepting the client's OAuth token to manage access, then you are responsible for validating that token and its desired usage on your systems and who that token is authorized from.
A better choice is to perform authentication and authorization on the backend (your web server for example). Then you can implement the Google OAuth redirect to send the OAuth token to your servers. You are protected in that only authorized origins (your domain name for example) and authorized redirect URIs (an endpoint on your web server) can be involved in the authentication process. You then store the token in your client session, renew when necessary, add authorization scopes as required, etc.
I frequently use both methods (client side, server side) and both work well.
Thought I'd add a postscript here, related to the recommendations for mobile apps in Financial Grade APIs, to use Claimed HTTPS Schemes to receive login responses. This restricts use of the client id to apps with your digital signature.
For further info, see my blog posts, which describe code samples that anyone can run:
Android Code Sample
iOS Code Sample
Only native and one page apps don't have a client secret, so they have to switch to something else. Here the necessary protection is the redirect URL. For web hosted one page apps this is not a problem no matter how it is set up. They are hosted exactly on this redirect URL. For native apps another step has to be done. Android and iOS allow the use of "App-Claimed https URL Redirection". This ties an https URL directly to the app. These claimed URL redirections can be requested and must then be confirmed via signature on a specific address: https://developer.android.com/training/app-links/verify-site-associations.
With this method, in order to use a foreign client_id, the https redirect must be intercepted by the fake client (only rooted environment, which most phones are not).
With a lot of effort, a fraudster could run another frontend with the same client_id.
In a use case like this:
Using the API generates costs (e.g. own API)
Advertising on the frontend generates revenue
this is a reason to rethink the architecture.
In a use case described by you, this isn't a problem, as you don't own the API resource. The resource owner, which is the logged in GCP user, will have to pay for their GCP usage. On public clients, you cannot have the client itself authenticate with the authorization server (only the user is authenticated).
I am creating a native Android app which currently uses Firebase Auth to handle user authentication. I have a MySQL database behind a PHP site and I'm building a RESTful API to access those services. I would like users who are authorized to be able to access limited features and data.
In this scenario, what would be the approach to handling the permissions on the backend server? I'm new to Auth techniques such as OAuth etc, but I get the feeling that might be part of this solution, so feel free to talk to me like I'm an idiot. :)
[edit]
My backend has similar permissions to Facebook; such as content is visible as either private, friends or public.
Regards
It depends on your security design.
The easiest way is to have a role-based security - use OAuth2/OpenID Connect just for authentication (ask for an ID token, not access token). Then you must get a list of roles for an authenticated user. The roles could be part of the ID token or the API server could get them from another source (e.g. its database). If the role retrieval is an expensive operation, you could consider issuing your own token (JWT) containing all the info you need.
If you wanted to delegate just some of user's permissions to the mobile app, you could register the API scopes (permissions) to the OAuth2 server and the app could ask the user for some of them. As an example, if your application wants to access Google services on behalf of its user, the application asks for an access token with specific scopes (e.g. reading GMail inbox). But this is probably not what you want.
Edit:
If the objects you deal with have access rights defined on themselves (private, public, friends visible), then just get a user identity (ID token) from the OAuth2 server and check the permissions when someone requests such an object by your API. OAuth2 itself cannot help you with that.
And for your Android app, use the Authorization Code Grant Flow as described in the OAuth2 for native apps RFC.
Been doing some reading regarding OAUTH2.
So...
Authorisation Code Grant: Is for users who want to access MY application/API through a third party application. Example: A user through Flicker wants to access MY photo printing API. In this case Flicker will do all the redirection and the OAUTH2 flow with MY servers. Access token is provided and 3rd party application can use MY API as needed. The application developer will need to register to get the client id and client secret.
Implicit: Same as above except the mobile/app doesn't have a back end server to safekeep the client secret. The mobile app will handle redirect and OAUTH2 flow. Access token is provided and 3rd party application can use MY API as needed. Refresh token not supported. The application developer will need to register to get the client id.
Resource Owner Password Credentials Grant: In this case, this is MY mobile/web app that I distribute to my users through the typical iTunes/Play stores. The users strictly use MY app to do their day to day stuff. MY mobile/web app will ask the user for Username/Password and post them to MY back end where it will authenticate and then provide back the access token.
Client credentials grant: This case is used for application to do internal machine to machine stuff. I.e: MY App1 accessed MY App2, in the back end somewhere.
For now I do not foresee sharing my API with 3rd parties and my users will install MY app through iTunes/google play. I suppose that Password Credentials is good for me right now. Eventually if I want to open up my API to the rest of the world I will have to implement Authorisation Code Grant
As I searched around for this subject, I came across this link: https://alexbilbie.com/guide-to-oauth-2-grants/ which has a nice decision flow.
OAuth2 is used when you want to authorize/delegate access on your resources to a client (third party application).
There are at least 4 actors:
The authorization server
The client
The resource owner
The resource server
The application/API is the resource server. It stores and manages all resources of the resource owner.
The client is the party who want to access on those resources.
The authorization server is the server who authorize client to access on resources by issuing an access token.
Authorization Code Grant is designed for confidential clients (able to keep their credentials secured).
Implicit Grant is design for public client (not a confidential client) and especially for scripting language applications (JS...)
Resource Owner Password Credentials Grant is designed for any type of client but supposed that the client knows the password credentials of the resource onwer. In general this grant type is dedicated to trusted clients only.
Client Credentials Grant allows the client to access on its own resources (in this case the resource owner is the client).
The use of the Resource Owner Password Credentials Grant should be avoided, however it remains a good solution for legacy applications and if there is a trusted relationship between the client, the authorization server and the resource server.
In our application we provide user authentication possibility which gives him additional rights and functions. Now we need to add an ability to login into our application using social networks (Facebook, Twitter, Google+, LinkedIn). We don't need any functions of these networks.
I've read these articles about social networks authentication on Android:
LinkedId
Facebook
Google+
Twitter
All of these networks provide their own Android libraries which handle authentication process. I don't know if I need to use them (they have different APIs and seems to be quite "heavy"). I also found 3d party library which handles all of the needed networks.
Now what I don't know:
After user logs in into any of these networks using appropriate library mentioned above what do I have to send to OUR server to login him into our application? Is it OAuth token (but it seems to be valid only for mobile application which aquires it), SN user id, email or anything else (let's call it access token)?
After access token is sent to the server what server has to do with it? For example aftet successful login through any of SN user tries to use one of the features our application login provides. Each of these features needs server request. So when one of these requests comes to our server does it need to check if access token is still valid or it must just create our user instance once token comes for the first time and later it doesn't need it anymore?
Do I need to store access token locally on device or after it is sent to the server I can forget about it?
How to provide logout function?
Ok, I understand that this question may be not correctly formulated so please, feel free to ask for more info if you need it.
I am writing a Google App Engine application along with a CLI client, an Android client and a Javascript client. The purpose of this application is to allow one to control an Android phone on which the Android client is installed, by using either the CLI or the Javascript client.
Authentication plays a crucial role as a bug might allow a malicious user to control others' phones.
The Android client is written and works. It authenticates the user using this method. Basically, this give me a so-called SACSID token I can store in a cookie. When this cookie is set App Engine recognizes my user. The server application can then call the UserService to get a User on which to call getUserId(). getUserId() returns me an opaque string that identifies my user. So far so good.
Now I am writing the JS and CLI clients.
Because the CLI client has no reliable way of displaying a CAPTCHA or opening a browser, I suppose that it needs to use the Device API ("Client login" is not an option). This API requires using OAuth 2 for authentication. Also, I want the JS client to access the user's contacts, which also seems to indicates that OAuth 2 would be suitable.
If my user authenticates using OAuth 2, will I be hable to somehow transform this Google OAuth 2 token into the same opaque String that I get when the Android client connects ? If not, can I modifiy my Android Application so that it uses OAuth instead of a Sacsid token ?
To be more specific, I see three things that would solve my problem :
A way of getting an OAuth 2 token from the Account Manager
A way of exchanging the OAuth 2 token for a SACSID token
A way of getting the same opaque UserID both with the SACSID token and the OAuth2, but only if I can have both authentication system on the same application.
Something that seems similar to the third possible solution is to get the user's email address from both OAuth and the SACSID token, and to use that as the user ID. This however looks a bit clumsy to me :
Every time I receive an OAuth 2 request, I would need to call Google APIs to retrieve the user's email address (or build my own system of tokens which seems insecure and introduces many other difficulties).
The email address of a given user can change, making me lose the association between the user and his previous data.
Use End Points instead:
https://developers.google.com/appengine/docs/java/endpoints/
They use oauth2, they are easy to implement and have support for android IOS and Web.