I'd like to a make a mobile app that makes requests on behalf of a user. I understand the following OAuth flow:
Open user in web view to give my app access to make requests on their behalf
When they hit grant access, my server side app will receive a call with an authorization code
My server side app then needs to exchange the authorization code for an access token
My confusion starts in Step 2. Uber makes a request to my endpoint with the authorization code, but I have no way of knowing what user that authorization belongs to. I can exchange it for an access token and store it in a DB for 30 days, but I have no way of getting it back to the user to use to make requests.
One thought was I could have the user sign in to my app with an email address which I could then use as a key to get the appropriate access token from my server app, but I have no way of associating the access token with an email address in my DB table in the first place.
I'm wondering what the best practices are here. How is my mobile app supposed to know what access token to use for a given user?
(I reached out to Uber API support directly, but they asked me to open a StackOverflow question instead)
Obviously this is kind of a broad question and is highly dependent on what type of app you're building, what you want the user-flow to look like, etc etc but I'll do my best to point you in the right direction.
First, the Uber API has the /v1/me endpoint which will return the users first name, last name, and email address, among other things. So one possible flow is that a User opens your app, they then go through the whole OAuth flow, and once you exchange the authorization code for an access token you immediately use it (from the server) to make a call out to the /v1/me endpoint and then use either the users email address or UUID as a key in your database. If you used email address, you could just allow users to login to your app using this same email address and allow the account creation process to just be the OAuth flow.
I'm not a mobile developer, but my understanding of embedded web views is that they can use cookies just like any other browser. In that case, another thing you could use is sessions / cookies. Assuming you have some kind of identifier for your existing users, you could add that as a cookie for your web server and then when your user gets redirected to your web server with the authorization code, the attached cookie will tell you which user to associate the access token.
Finally, the Uber developer platform includes a state parameter in the authorization phase of the OAuth flow as seen here https://developer.uber.com/docs/authentication You could do something similar to what I describe in the previous paragraph, except instead of using cookies you could store the user identifier in the state parameter and it'll be sent back to you when the user re-directs. You can use that piece of information to tie the access token back to a specific user in your DB.
I hope that helps! Don't hesitate to reach out if you're still confused.
Cheers!
Related
So, Here is what I understand about how Google Oauth2 works.
Every application or a website (client) needs to register its project and get a client_id and a client secret.
The client_id and a redirect uri are used by the client to make an authorization request to the auth url on behalf of the user who is logged in.
When this happens, there is a pop-up and the user(resource owner) is prompted to allow or deny access to the user's protected resource for the client.
If the user accepts then the user is redirected to the redirect uri from where the client or the application can get the authorization code.
This authorization code is further exchanged for an access token from the OAUTH URL. This access token is later used in the Api calls the client make.
The problem is with the step 3. I am not running a web app or a website. Rather an application that can make curl function calls. Step 4 and step 5 are doable but, How do I bypass the step 3 as I don't have browser capabilities? Is it even possible?
Also can someone please tell how an android app does it? Because even the android app shouldn't have an inbuilt browser. Thanks in advance
We have the OAuth2 for Devices flow to take care of the problem you are trying to solve See this
The user can authorize the app from a different device that has a web broswer.
Every application or a website (client) needs to register its project and get a client_id and a client secret.
Correction / clarification: Any application that wishes to access private Google data must first be registered on Google Developer console. If the data to be accessed is public then a API key can be used. If the data is private then either Oauth2 credentials must be created or service account credentials.
Oauth2 credentials allow a user to grant an application access to a portion of their data (Denoted by scope) the application is identified by the client id and client secret.
Service accounts would allow for preauthorized access to private data normally owned by the developer working on the application. They do not popup the request for user authentication. Please see my article on this Google Developer console service account I don't want to go into service accounts here as you appear to be concerned with Oauth2.
2 . The client_id and a redirect uri are used by the client to make an authorization request to the auth url on behalf of the user who is logged in.
Correction / clarification: The first step in the Oauth2 dance is to request access from the user. This is done via a web page.
https://accounts.google.com/o/oauth2/auth?client_id={clientid}.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/analytics.readonly&response_type=code
Redirect uri is used to tell the authentication server where to return the authorization code to. In the event this is a web page application it would be the full location to a webpage capable of handling the next steps in the process. As you can see I have not put a web page in. This is in sense localhost. It tells the authentication server to just return the code to where ever it was I just sent my request from. It is used in windows applications and probably android although I am not an android programmer so I am not sure its just an educated guess.
4.If the user accepts then the user is redirected to the redirect uri from where the client or the application can get the authorization code.
Correction / clarification: Its probably your code that's redirecting you. I don't think its the server redirecting you but I may be wrong. The authentication server can send the code were ever you want it would be up to the developer to redirect the user someplace after the exchange.
5.This authorization code is further exchanged for an access token from the OAUTH URL. This access token is later used in the Api calls the client make.
Correction / clarification: access token is only good for an hour and you might also get a refresh token back which can be used to get a new access token.
Addressing your problems
The problem is with the step 3. I am not running a web app or a website. Rather an application that can make curl function calls. Step 4 and step 5 are doable but, How do I bypass the step 3 as I don't have browser capabilities? Is it even possible?
This is going to depend upon which api you are going for and whos data this is. If this is data owned by your users then request access from them save the refresh token and then when you need to access it again in your curl script you can just get a new access token and you have access. Its only the initial authorization you need to bother your users with.
Second option if this is your data that you personally have access to you may be able to user a service account. Service accounts are like dummy users you can preauthorize their access. I could create a service account add it as a user on a folder in my google drive and it would then be able to read and write to my google drive with out that popup window.
Also can someone please tell how an android app does it? Because even the android app shouldn't have an inbuilt browser. Thanks in advance
I am not an android developer I think part of it is magic in the Android SDK the credentials you get for android apps are even different. Cant really help with this one.
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 would like to discuss a common scenario: An app wants to authorize users using multiple OAUTH providers, such as Facebook, Google+ or Twitter.
Essentially this question has been asked two years ago here Mobile API Authentication Using Existing Web App with Multiple OAuth Providers and stays unanswered, so I will elaborate a bit further. (I will use Facebook as an example for the OAUTH2 provider, so this does not become too generic.)
Essentially, user registration works like this: OAUTH/OAUTH2 providers typically provide a workflow where a (mostly short-lived) token is obtained from a provider either via the AccountManager on the mobile device or a login dialog such as the "Login with Facebook" button. The token is then shipped to App Engine by calling a REST endpoint (either in the body or as an additional header, never in the URL).
The provider's AppId and AppSecret (here: Facebook) are store on App Engine and App Engine adds these to the token, then ships it back to Facebook in exchange for a (long-lived) token.
At this point both, client app and App Engine app have certainty that the user has been previously authenticated by Facebook. Also, if Endpoints Authentication is used to authenticate the call, App Engine probably has the Google credentials of the user and/or the ClientId of the app, and Google guarantees that the request has been made from the correct client app.
At this point, we can try to find the user in our datastore and let registration fail (or silently sign in the user) if it already exists, or otherwise create a record.
Until here I am pretty sure I'm on the right track. Now comes the problem:
Let's look at the datastore for this. Let's assume we have two entities:
User entity, where each user in our own system is registered under a unique user id.
Account entity, where each account is registered and where a userId field points to the User entity.
In relational database terms, we would say we have a 1:n relationship between User and Account.
For each User in our system, we keep a User record. In above example, we may have two accounts: Facebook and Google, which both point to the user and where the unique Facebook or Google id/email is used as account identifier.
Technically it would now be possible that the app uses the Facebook or Google account on subsequent requests. But we would have to store and look up the 3rd-party token on each request because we cannot decrypt it ourselves. We could ask the provider to do this, but that wouldn't make much sense either. Plus we would have to translate the provider's Account id to our own User id on each request.
To solve this problem I would most probably either create our own token or set up our own OAUTH provider which creates a token signed by our own system, and where the unique User id is used as identifier, and only use that token during subsequent requests.
Is this a good approach? Is anybody using a different better workflow? Does anybody see security flaws with this design?
Essentially it works around Google's endpoints system, but Google can only authenticate against their own systems, so if we want to offer sign-in using further providers, we will need to work around this, except if anybody knows a workflow where we can keep both, but then we have the problem that we can/should only add a single token in the "Authorization" header and REST principles discourage us to use custom headers to ship more tokens.
When your app authenticates a user, store an object in a session which contains an oauth provider that has been used to access the app and, optionally, a token to be used for subsequent requests.
Now you can check for this object in every call to the server. If the object is not present - a user is not authenticated, redirect to the login page. If an object is present, take a token and use it.
I use a similar approach for multiple authentication options, not only oauth. Except I don't need to store a token after a user is authenticated - I have no use for it within the app.
I'm trying Google Plus sign-in in an Android app (with backend support).
I could get access token and email from the user, but know I don't know how should I recognise this user from the server. I'm sending this to the server (email and oauth token) with a POST throught SSL
Of course I could recognise them with their email, but that would open the doors for everyone how knows another email that's on the database.
How could I verify that the user's correctly authenticated and has sent me the correct oauth token for this email?
Thanks!
Two thoughts:
1) Generally, you shouldn't be sending the auth token over the wire if you can help it. Instead you should be using a hybrid flow where the client gets a one time code when it authenticates, passes you this one time code, and you can redeem this for an auth token and a refresh token. Using this method, your server also has offline access on behalf of the user. See https://developers.google.com/+/web/signin/server-side-flow for details. However, I'm not entirely sure how this works with the Android library.
2) Regardless of (1), generally what you can do is to use the plus.people.get method on the server with the userID of "me" to get the user's userID and verify this against what you're expecting. See https://developers.google.com/+/api/latest/people/get for more details.
Yours is a perfect case to use the Authorization code flow.
See this link. It has some workflow diagrams that you might want to see. In your case the user should authenticate and receive an authorization code (and not a token!).
He would then send the authorization code to your server, you can exchange this code for access + refresh tokens. Have your client registered for the scope and have the client credentials.
The access token flow (called the implicit grant flow) is generally used when requests need to be sent directly from the user's browser.
And, as #Prisoner already mentioned, you will have offline access too. That would be a much better design.
EDIT - you might also want to take a look at What is the difference between the 2 workflows? When to use Authorization Code flow?
I am trying to get Authorization for Google Buzz,Contacts from an Android application.
The flow is similar to this.
The user chooses if he wants to use Buzz.
Using OAuth/Client Auth, we need to get a one-time authorization code.
This code would be used by a web service to periodically read Buzz feeds.
Now, the problem is how do I obtain the authorization code (Not temporary token) from the Android App and send it to the webservice.
I could use the normal OAuth2.0 and use my webservice as the redirect URL to obtain the code. But in that case how can I let the webservice know that the code pertains to which user?
Can I pass extra information with the OAuth dance?
I strongly recommend using OAuth 2. The flow is much better for the end user and it's a lot easier to implement something like this. Additionally, it uses bearer tokens, which means that you can maintain your refresh token server side where it's actually secure and only ship access tokens to the Android when they're needed.
The downside of this approach is that effectively every time your app loads it needs to phone home to get the latest access token. But once it has that access token, it can make whatever API calls it needs to, directly to the Buzz and Contacts APIs.
However, to do this, you don't pass extra information with the OAuth dance. Instead, your Android app needs to have already securely identified which user is signed in with your app, and then make sure the server only ever sends back access tokens associated with the authenticated user. If it doesn't have an up-to-date access token for that user, it would need to make a request out to Google's authorization server to get the latest access token, and then pass it up to the client. So there's certainly a strong potential for some latency there, because that generally needs to be a synchronous call, but that's usually a small price to pay for the advantages OAuth 2 gives you over OAuth 1.