Android WebView wrapper authentication methods - android

I'm wrapping a Rails mobile website with an Android WebView wrapper, but it's also supposed to be available through the browser as well. The website is using Google/FB OAuth authentication, but that's not essential.
When the wrapper is used, I wanted the user to be already signed in with its primary email.
Are there any secure methods to achieve this? Something which will not allow using this method in the browser?
I was thinking about sending some kind of checksums / secure tokens but this could be easily reverse engineered.
Would the authentication with device id and android id be enough? I mean, these are available publicly for other apps so I guess possibly not. Maybe there is something that is unique to the app instance and private?

There is nothing automatically secret in an instance of an Android app that your server could verify. Using Google/Facebook OAuth login is a reasonable choice.
You can use the Facebook SDK for Android to allow the user to log in using their Facebook account, and as a.ch. mentions in the comment you can do the same with the Play Services SDK to log in via their Google account.
In both of these cases, this works because there is a local broker app (Facebook, or Google Play Services) that is trusted by the identity server (facebook.com, or google.com). The broker app has the user's credentials, can verify the identity of the app that is requesting access, and can display a view where the user can approve/reject the request. Once the identity server knows that the user has logged in on the device, knows the identity of your app, and knows that the user approved the login request, it can safely send back a token to your app via the broker. That token allows whatever permissions your app requested and the user approved.
Your WebView can then include that token in an initial request to your rails server, which checks the token with Facebook/Google. From this point, the code should look similar to the existing desktop web, at least with respect to user authentication.
You can download the Facebook SDK for Android from https://developers.facebook.com/android/, and you can get the Google Play services SDK in the Android SDK manager ('android sdk') under Extras. Both have tutorials to help you get started.

Related

WSO2 Identity Server: How to handle Android App login with Google

Currently, we have the following landscape: a back-end (Play + Scala) server that provides a RESTful API. In addition we have a front-end Web client and an Android native app client. Now we want to add the WSO2 Identity server (v 5.1) to maintain user logins everywhere.
The problem that I am facing is with the native android app integration. I have a successful Google Sign In and as a result I have the Open ID token. According to https://developers.google.com/identity/sign-in/android/backend-auth I should send the token to my back-end server (WSO2IS) where the token should be verified against Google authorities and if the token is legit, it should sign in my user in WSO2IS. Note that if such user doesn't exist in our system, it should first be created and then signed in. Unfortunately I don't find a way to send the token to WSO2 Identity Server.
What I have done so far:
1) configured Identity Provider (IDP Google Federated Authenticators)
2) configured Service Provider where Local & Outbound Authentication Configuration points to previously defined Federated Authenticator Google
3) configured some claims in both IDP and SP
Then I start playing with the endpoints:
/oauth2/token
/oauth2/authorize
But using this is not what I want, because these endpoints will generate me a new token instead of getting the one I have.
Then I found out about Open ID prompt=none (http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest), and I also tried to invoke authorize and pass the open ID connect as Authorization: Bearer <token> header when I call
oauth2/authorize?prompt=none&scope=openid&client_id=fzOPC3fCftkgC3xcLn7ZqjXiY_Ya&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A9443%2Fcommonauth
Also tried none+login.
Is it possible to do this with WSO2IS? To register/login a user by passing a Google Open ID token?
If it turns out what I am trying to do is not possible, I come up with the following workarounds:
1) Create a custom service that will validate the token and if legit will register a new user. This is just an idea, I don't know if it is possible and also if I need to write the code myself why should I use the WSO2 Identity Server?
2) In the Android App I should drop the native Google sign in support and use a WebView where we will use the pretty clear and standard Web App flow. I cannot evaluate what I will lose by using web view instead of the API, but it seems wrong. It is natural that on Android phone you should sign in seamlessly with your Google account.
If I need to use one of the workarounds, please advise me which one is the better approach? Or propose a new one.
EDIT 1: Workaround 2 discarded based on
Browser popups is the preferred way for web apps to redirect the user to the IdP. Mobile apps on platforms such as Android or iOS should launch the system browser for that purpose. Embedded web views are not be trusted, as there’s nothing to prevent the app from snooping on the user password. User authentication must always occur in a trusted context separate from the app’s context (e.g. the browser).
This is taken from http://connect2id.com/learn/openid-connect#auth-request
If it is not possible to use a WebView (for security reasons) and in Android you can only open the browser, but you cannot command it with startActivityForResult. This means that even if the user sign in, the browser won't close automatically and it will hand out there until the user close it. In addition the browser won't tell your app that the user is logged and the app should find out by itself (honestly I don't know how: you cannot do server push or something similar, because you can sign in with the same Google account on multiple devices; and the second obvious option is server polling but the app doesn't know for which user to ask).
EDIT 2: A new view over things
When configuring Google for a Web Client login, there is a field for authorized URI (the callback that Google invokes to send the token back). For WSO2IS, this is https://localhost:9443/commonauth. So, this should be the URL that we need to send back the token in the Android app. I start testing with Postman, I am sending the following request:
POST /commonauth?code=eyJhbGciOiJSUzI1NiIsImtpZCI6IjhhNDJhODMzN2IxMmI5MzI5NGIyNGU5NDY5ZTViZWIwZGFhMWJlNGUifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJpYXQiOjE0ODQ2NDczNjIsImV4cCI6MTQ4NDY1MDk2MiwiYXVkIjoiNTM3ODQyNDY1MDM4LWpwZjRpYmE0cGI4YjN1bWY2aGhpYTFnNTJuODR1N2k1LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTAyMjMwNjU1MzQxMzczODU4NDI2IiwiYXpwIjoiNTM3ODQyNDY1MDM4LXJmYmt0YTJ0MWFlazgycDZrNzloNXZrb2ppcXVvMTQ0LmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkRhbmllbGEgVmxhZGltaXJvdmEiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy1YQlNmUXgweE4xcy9BQUFBQUFBQUFBSS9BQUFBQUFBQUFBQS9BS0JfVTh0eTQyZHpfdk5sUFZ2Z01jcjUxUVJBWXBWMjNBL3M5Ni1jL3Bob3RvLmpwZyIsImdpdmVuX25hbWUiOiJEYW5pZWxhIiwiZmFtaWx5X25hbWUiOiJWbGFkaW1pcm92YSJ9.VMspUYeaAVHavEyoK3Hsss0pyZMHu-4QozucTAU-CLXnjAoaFbPBirslX7VpS4wvwHPge0AE5gHpIzAl1el_ufkhiu2NJn_LKo48Ve3HNj9igjnwD2nW_PGOqlYPoWV5UtFlKyUxi72qvLOCkYwsPuKVzA9irD-vGm3U2U3wBu_OQrJzbhdU9lp3aG4F0tQgQi-NPtEZY7Xgu-Om3qmarByhJYjxBPHEWzuyuQ2F9xY65t0mnd7gVAr2F5_aBHemjVx8V9lQc4eyRFjE3g_9ZgYn9xX9w8TwCXO9VpkdVRdFWQ07RFjFz915FO5KX9x4UNAu6H1Jop9ug5oiVCrmFw HTTP/1.1
On server side, this result in an error: Context does not exist. Probably due to invalidated cache. In server logs I found:
DEBUG - Session data key is null in the request {org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator}
ERROR - Context does not exist. Probably due to invalidated cache {org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator}
I've looked at the code for DefaultRequestCoordinator, it seems I need 2 more parameters: type and sessionDataKey. I think the type should be set to openid, but how can I get a valid sessionDataKey?

How integrate loopback third-party login for android

My project includes web and android client. I want to combine Google cross platform sign-in and loopback third-party login.
In my scenario, I will never ask username and password. User only uses Google sign-in button for authentication and authorization on both web and android app.
Lets assume, it's the first time you logged in with Google sign-in through my web site. In loopback third-party scenario, if you are not existing on db, it creates an account corresponded provider and external id. (In this case provider is google and external id is your unique google id). This is for web, loopback-example-passport
So, assume that above scenario for android. You click only Google Sign-in button and then loopback server will able to do above things (as web)
Is there a built-in way in loopback for this? If not, how can I integrate this scenario in loopback properly?
Well it's a little bit old question, but I've encountered the same issue on android, but with facebook third party login.
I didn't find any trivial solution, so after a lot of struggle tried different approach: (change facebook to google for your case)
UI user presses 'login with facebook' button (provided by facebook sdk for android)
UI User signs in with facebook credentials
Client side gets user's access token from facebook
Client side encrypts the access token and passes it to the server.
Server decrypts the access token, and talks with facebook graph API using access token - for validating the token, and if needed, for getting additional info related to requesting user.
Assuming it's valid, server check's if the user already has local account (can be checked with email or id):
6.1 If user doesn't have an account, we create a new one with the Facebook User ID or email (loopback requires password so a random one can be provided), this will assign our own unique UserID and issue our auth ticket (user.createAccessToken(ttl, callback)).
6.2 else, continue just with assigning auth ticket to user for this session

Android App registration / Authorisation

I am quite new to android and recently started building an application which requires
Registration using a google id.
Continuous interaction with a back-end server.
For the registration , i was wondering if it is possible to have a python webapp on Google App Engine which has the OAUTH2 authentication .
This page if opened in a webview should return the token to GAE (please correct me if i am wrong here , because i am not sure the token won't just go directly to the app).
Then again on the backend i generate a token(newly generated) and update the user tables with this new token and pass this onwards to the application.
Every subsequent request made by the app will be referenced using this token.
Is this feasible or is there a better standard way to do it (i do not want to use the login info already stored in the phone) ?
Also , how can i get information from a google account(name,email) like Facebook has access to the graph is there a google counterpart ?
As far as I understand, you implement your Android app using WebView. This means that the app interacts with the server the same way as the built-in Android web-browser. As a result you don't need to add anything special to your Android app with regards to authentication.
Built-in Users service
In GAE, you get out-of-the-box support for three different types of authentication where all of them are designed in a way that your app doesn't store user credentials but rely on user authentication from identity providers:
Google Accounts (e.g. jonny#gmail.com)
Google Apps Domain (e.g. jonny#mydomain.com hosted in Google Apps)
or Federated Login (a.k.a. OpenID, e.g. Google, Yahoo!), which is going to be replaced by Login with oAuth2 (OpenID Connect)
All three types allow your app only access to very basic information of the user. Enough to match a returning user of your GAE app to their data, and an email address or unique ID, but that's it. For more, see below (oAuth2 consumer).
In appengine console, you can select your preferred authentication type in page Administration > Application Settings.
Whatever of these types you use, in your Python code you can use GAE's Users service which will deal with the authentication of your users. Basically, you just write something like:
from google.appengine.api import users
user = users.get_current_user()
if not user:
# The user is not signed in.
else:
print "Hello, %s!" % user.nickname()
On development server, you will be prompted with a dummy login page for requests where you require login or admin login. In live environment they will be replaced by GAE with real login page flow. There are also articles linked in the docs with HTML/JS examples if you want to show custom login pages to your users, for example User Experience summary for Federated Login
oAuth2 for authentication and authorization with Google
Regarding oAuth2, with the built-in authentication it is rather easy to integrate the builtin oAuth service, so your GAE app becomes a service provider, i.e. a user of your GAE app can share data with any 3rd party app or website through some simple API. You also can have your GAE app consume data that your users have stored somewhere else (e.g. Google) and they want to share with your GAE app (consumer). If you are especially interested into accessing user data in Google services, there is this good overview.
Custom user management
Finally, you could implement your own authentication mechanism, rather than relying (and depending) on GAE features. For example you can implement your custom user management based on webapp2. This means that you have control of the user-accounts and credentials, but aside of eventual security risks the disadvantage is that it can be really hard and tricky to integrate services and APIs like Google Cloud Endpoints.

Authenticated communication b/w Android app And GAE server using OAuth2

New to OAuth2. I am writing an Android app that communicates with an App engine server application.
The app needs to authenticate itself with the server on behalf of the user, using Google account info of the user. The server needs to retrieve the user's basic info and create an account . That's the easy part and I know how to do this.
Furthermore, the Android app will also have the user authenticate himself/herself using Oauth2 and retrieve basic user info using Google account info of the user. I can do this as well.
This is where I need help Assuming the previous steps have been completed successfully, how can I use the Android app (where the user has logged in) to communicate with the server securely using the user's credentials.
Any ideas or am I missing something obvious?
The Android to App Engine OAuth2 communication is documented in this answer:
google app engine oauth2 provider
Using OAuth, 1.0 or 2.0, doesn’t matter in this, leads to the app obtaining an access token - then based on the API of your server, you pass this access token with requests instead of login and password. I guess the way to attach the access token string to URL requests may be slightly different between different APIs, see the documentation for yourself. Or if you are making the server app at the same time, then you need to figure out your way to do so (like sending a HTTP header Authorization: OAuth access_token=abcdefgh….

On Google App Engine, can I relate a Google OAuth 2 Token and a SACSID token I got using Android's AccountManager?

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.

Categories

Resources