OAuth 2.0, Android and cookies - android

What is the point of using OAuth 2.0 client-side authorization in Android if built-in WebView browser doesn't have access to cookies of default user browser? I mean, if I open some oauth-url (e.g. http://blablabla.com/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token) in WebView - the user will anyway be prompted to enter his credentials to sign in to "blablabla.com" social network. Because even if he is already signed in with some of his browsers (Opera or Dolphin, or default browser), the WebView browser doesn't know anything about corresponding cookies.
EDIT:
I'll try to make it a bit clearer.
The main goal is to simplify sign-in procedure in my application. I'd like to implement such mechanism that we can see on many web-sites: "Login with... Facebook/Google/Twitter/whatever". And in desktop browser that approach works perfectly, because the end-user is already signed in to aimed service WITHIN THIS BROWSER. So basically to sign-in in to my site all he needs is:
Press button "Sign in with..."
On redirected window/popup press
"Approve/Confirm".
Get redirected back, already being signed-in.
The main benefit is that user doesn't need to enter his email/name/whatever - I've already extracted it from his social-network account.
And I'm wondering how to get same effect on Android. The problem is that, as I can see, we can't let user avoid entering password, because the application (WebView) never knows if he is signed-in to some outer service or not. That's why user anyway will be prompted to enter some of his details and all of OAuth benefits become annihilated.

The workaround depends on what you are trying to do. It's not clear to me, looking at your question again, because you do not explain your use case. Instead you are indirectly asking for something that looks very broad as if you want to maintain an Android system-wide login state that spans over multiple applications using shared cookies.
Due to security reasons that is neither good nor wanted. A rogue app could do whatever it wants to do with existing access tokens requested by other apps or just temper with or read existing cookies created and maintained in other apps.
Assuming you are trying to authorize your own app access to a web service using OAuth 2.0 by letting the user log in with a WebView, you need to implement your own WebViewClient, override its onPageStarted or onPageFinished method and check whether the URL argument matches your redirect URL.
If there is a match you need to extract the access token from the URL string. If there is also a refresh token available, then extract that one, too.
(This however only works for a certain type of OAuth flow, which adds the access token to the redirect URL.)
Now you have at least an access token available. Store that token in the private preferences of your application and use it in your service requests until you get a 401 not authorized error message back from the service. At that point you can use the refresh token if available to request a new access token or you have to show the login WebView again.
If you are trying to access a Google service from your app you may find the article Getting started with the Tasks API and OAuth 2.0 useful.

Have you considered launching the browser externally (non-embedded)?
That will benefit from existing cookies and also give users the trusted UI they are most comfortable with when entering credentials to these services. (in other words - users see the SSL lock, the correct URL in the address bar, etc.)

Related

Accessing user data in a application using google api on an embedded device without a browser

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.

Android App: How authenticate via web-based login

I am writing an Android app that makes calls to a REST Api. The user must be logged in and in order to do so, he must authenticate on the server which in turn redirects to the Identity Provider of my university.
My idea was to let the user log in via the android in-app browser and then extract the session cookie (and csrf, if necessary) into the app's AbstractAccountAuthenticator once the user is logged in.
How can I do this? I would also be happy about some helpful links. And secondly, is my way really the way to go?

Shouldn't OAuth2 redirect the user to the external browser instead of just loading the login screen into WebView

what is the correct way of handling OAuth on mobile devices? Android, iOS, etc..
As I am seeing most apps just do load the login screen into an in-app browser like WebView, or so..Isn't it actually trampling the whole principle of OAuth? because I can as a developer easily read the password the user enters into the textfield..Is there a way how to do that with the startActivityForResult pattern (on Android particularly)? Because when the user would enter their login and password into the main system browser, it should be a way more solid approach to maintaning security and trustfulness for the app?
Passing data between the app and the browser
You have to read the response (the reloaded url) from the page, after the user has logged in, to get the authorization code used to request the authentication and refresh tokens. If a (default) browser has to take responsibility for returning the authorization code for you, then it has to have (documented) implementation of receiving such intents for such a result.
Letting the browser know your app's credentials
There is another even more serious problem - usually you request authorization/authentication using your app's credentials (client id + client secret). You put them somewhere in the headers or in the url as parameters. You'll have to provide them to the browser to put them in the headers/url of the request for you.
Combined:
And when the browser has both authorization code and your app's credentials it can acquire auth/refresh tokens for the user's account and not only have access to it but also pretend to be your app. Having in mind that this is the built-in browser that comes with the device the user will be calm because he'll probably trust the manufacturer as he's buying it's device but can the app's developers trust the manufacturers? And when a user chooses a 3rd party browser as default and/or uninstall the built-in one?
In short:
Instead of the user trusting the application he/she installs, both the user and the developer have to trust the 3rd party - the browser

Android SSO (Single sign-on) for app

Is there any free single-signon mechanism for Android that gracefully works with non-webapps? Say, something along the lines of...
You launch my app and use it until it makes a request from the app server that requires authentication. It responds to that request with a random token that the server will associate with you for a short time.
The app presents you with a username field, a password field, and a submit button.
You enter your username and password. The app then forwards your username and hashed password, along with the token generated by the app server, to the login service.
The login service determines whether or not your username and password are valid. If they are, it digitally timestamps and signs the token, and returns the signed token to the app.
The app relays the signed token to the server.
The server checks the signature, satisfies itself that it's valid and signed by an authority it trusts, and proceeds as though the user had presented IT with a valid local username and password instead.
I suspect I'm just getting lost in nomenclature, but the impression I've gotten so far is that all the usual SSO providers -- Twitter, Facebook, etc -- only allow users to log in using a normal browser, and that you're either not allowed to do what I described, or they do something to make it effectively impossible with anything besides a normal browser (like dynamically creating the login form via Javascript in an effort to prevent developers from trying to use their own apps as a login facade).
Alternatively, does there exist any workflow like THIS...
You launch my app and use it until the web service requires you to log in. The app server generates a token and returns it to the app.
The app spawns a new browser via intent that sends you to the login provider's web site, passing the token via intent to the browser (and ultimately the provider) as a POSTed formvar.
You log in using the browser window, and the browser window closes -- returning you to my app.
The login provider signs the token, then sends it directly to my app server via HTTP POST so I can note its submission, verify the cert, and treat it as though it were instead a valid username and password submitted directly by the user to the app server himself.
Have you tried or think of using Firebase? https://firebase.google.com/docs/auth/?hl=es-419
It has some useful tools, you can sign-in with multiple social connectors and user/password as well, and they provide a library to integrate the whole UI and server flow, they even take advantage of google smart lock for you.
Take a look at https://github.com/firebase/FirebaseUI-Android I used it in a personal project and saved me a lot of time.
What you described in Alternatively section looks like Authorization Code using Proof Key for Code Exchange (PKCE) OAuth 2.0 grant
https://www.rfc-editor.org/rfc/rfc7636
The flow is the following:
Your app generates a random key (code_verifier) and it's transformed value (code_challenge) and navigates to authorization server with code_challenge as a parameter
Authorization server redirects back to your app with authorization code
Your app sends authorization_code and the code_verifier to the auth server to get the authorization token
Server uses authorization_code and the code_verifier (it already has code_challenge, so it can verify that code_verifier is correct) and then returns to your app with the token.
On the practical side of it you can use something like Auth0 to implement it in your app.
Use Android Account Manager for SSO.
Providing references below just for knowledge. You have to dig into account manager.
Android developer: https://developer.android.com/training/id-auth
Blog with example: https://www.zoftino.com/android-account-manager-&-create-custom-account-type

Is it possible for an Android application to use Open-ID service?

I have a C/S solution, which take Android as its client and PHP as its server.
I have my own account system.
I'm wondering whether I could provide my user to login my system with Google Account?
I saw there are web-solution for this, like this stackoverflow.com could use Google Account to directly login.
Is there a solution for C/S system?
Not without a web browser.
If the user isn't logged in to google (or any other provider), he has to authenticate with the provider first. This is done via a web browser, and you shouldn't even try doing it in any other way (for security reasons, the user should be sure that he is connected to the provider, for example by seeing the url in his browser).
However, even if the user is logged in, the provider needs to know that -- usually using a cookie. And cookies are stored within a web browser. So in theory, you could parse the browser's cookie file, and then try immediate authentication, but that won't work until you login and authorize the relying party via a web browser first.

Categories

Resources