Providing Google login in Metro app, avoiding repeated permission-grants (Oauth2/Google OpenID) - microsoft-metro

I have the following situation:
I'm currently attempting to write a Metro-style application, with the ability to let the user sign in with his Google account, and the app requestion several permissions, as Userinfo.profile and Userinfo.email.
For this I'm currently using OAuthv2, and requesting the details worked out fine (after quite some effort and research).
Url used :
const string url = "https://accounts.google.com/o/oauth2/auth?" +
"client_id=" + clientId +
"&redirect_uri=" + "urn:ietf:wg:oauth:2.0:oob" +
"&response_type=code" +
"&scope=https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email" +
"&access_type=offline";
Now the problem is, if I want the user to stay authenticated, I'd either have to do it by saving the token at the clientside, by the user, or find some way to log in using Google, keep the session and check if he is authenticated.
Problem is, I don't know how to perform the latter, and have no idea how to use it.
At the moment, every time I open the application, the user is redirected to the google authorization page, where the whole procedure starts over and over again at each restart.
What I want to accomplish is that if a user logs in, I have some way of identifying him, and not always put a burden on him by re-requesting permissions for the given details.
I looked into OpenID, but I always get
<?xml version="1.0" encoding="UTF-8"?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">
<XRD>
<Service priority="0">
<Type>http://specs.openid.net/auth/2.0/server</Type>
<Type>http://openid.net/srv/ax/1.0</Type>
<Type>http://specs.openid.net/extensions/ui/1.0/mode/popup</Type>
<Type>http://specs.openid.net/extensions/ui/1.0/icon</Type>
<Type>http://specs.openid.net/extensions/pape/1.0</Type>
<URI>https://www.google.com/accounts/o8/ud</URI>
</Service>
</XRD>
</xrds:XRDS>
As a response on this url :
https://www.google.com/accounts/o8/id?openid.mode=checkid_setup&openid.ns=http://specs.openid.net/auth/2.0&openid.return_to=urn:ietf:wg:oauth:2.0:oob&openid.ns.ui=http://specs.openid.net/extensions/ui/1.0&openid.ns.ax=http://openid.net/srv/ax/1.0&openid.ax.mode=fetch_request&openid.ax.required=email,firstname,language,lastname,country&openid.ns.ext=http://specs.openid.net/extensions/oauth/1.0&openid.ext2.consumer=https://www.google.com/accounts/o8/ud?openid.mode=checkid_setup&openid.ns=http://specs.openid.net/auth/2.0&openid.return_to=urn:ietf:wg:oauth:2.0:oob&openid.ext2.scope=https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email
Am I building it wrong ?
If any suggestions, on either how to perform this 'correctly', what I'm trying to accomplish (an integration with google, allowing the user log in using google email, and only if he hasn't authorized the application, ask him to do so, plus finding a way of who he is when logging in for a second+ time), or on how I could do it, please feel free.
Besides, by using the stripped down version of the .Net 4.5 framework, it seems I'm unable to use OpenID libraries as they rely on the full 4.5 .
*Edit* Looking at MSDN this comes up :
To support SSO, the online provider must allow you to register a redirect URI in the form ms-app://appSID, where appSID is the SID for your app.
Does this mean it just isn't possible? Because at google I can only request a key for a domain with http(s):// ?

Have you looked at this? https://developers.google.com/accounts/docs/OAuth2Login
It looks like you are using the Webserver flow and are requesting offline access. This should give you a refresh token after you swap the code. Hold onto this token in your application. If you do an authorization for login as well, you'll get a token back and you can use that to get the userid of the user at Google
Your application should keep track if you have a valid refresh token for a particular user. Then use that token to get the current credentials. You can use tokeninfo enpoint to validate the token. If you have a valid token for the user, there is no need to send them through the code flow to get another refresh token.
If you use the tokeninfo endpoint, the userid field is only present if the https://www.googleapis.com/auth/userinfo.profile scope was present in the request for the access token. The value of this field is an immutable identifier for the logged-in user. Store this and you should have a durable identifier of the user.

Related

OAuth - what to store on disk

TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?
I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.
The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.
On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:
my server will redirect the browser to google (with the clientid, secret, etc.)
user logs in and it will be redirected back to the server with the oauth code
server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
the desktop app catches the parameter and stores it in an file on the disk
next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server
my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?
when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that
As it's normally the case in software development you have a couple of options depending on requirements.
The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:
Decide who the user is.
Decide if the user is authorized to perform the currently requested action.
The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.
Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.
Option 1 - Authentication without fine-grained authorization
Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.
If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:
repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
request offline_access when doing the first authentication.
With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.
Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.
Option 2 - Authentication + fine-grained authorization
If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.
For the authorization server implementation, you could either:
Implement it yourself or leverage open source components
⤷ may be time consuming, complex and mitigation of security risks would all fall on you
Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
⤷ easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time
Disclosure: I work at Auth0.
There should be no problem sending the access_token with every request since they are created for that purpose and are thus short lived. You can use the Google Authorization Server endpoint to verify a token instead of using it to do a request for a users profile.
If you're only relying on Google for authentication, here's how your workflow can look:
the client (desktop application, in your case) retrieves the
Google id_token following the user's log in, and then sends it to
the server
the server validates the integrity of said token and extracts the user's profile data; this could mean a simple GET on Google's endpoint to verify this token: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
On subsequent requests, nothing should change really, except that the user's login process will be automated (since he's given permissions & all), and thus much faster. #danielx is right, there's no problem with sending the token each and every time.

Is there any way to get LInkedIn company network updates w/o requiring user to authenticate via browser?

Since LinkedIn discontinued their network updates RSS feeds, I haven't been able to find any "simple" mechanism to gain access to update feeds w/o going through the oauth process requiring the user to authenticate first. The few examples I've seen posted here all assume you've obtained the auth token first. Is that even possible?
In case anyone else inquires: https://developer.linkedin.com/support/faq
If your application requires you to make API calls in an automated way
- without user interaction, you need to bootstrap the first access token request by manually signing in, and then ensure that your
application refreshes the token automatically prior to expiry to avoid
the need for additional human authentication.

Spring boot REST token authorization and authentication best practices

What is the best practise for authorization and authentication of users in REST spring boot?
I am building web app with standard pages + REST API for mobile. I looked at many articles about Spring security and basically most of them goes with some sort of fitler approach that will allow or block REST calls. In my case, however, I have some auth logic based on who the user is. For example, there is a /update API that updates user information, and user can update himself, but cannot update other person.
Initially I thought to use next auth schema:
User calls auth API and pass name/password or cookie
System generates short life token, saves in it's database.
User get this token, updates his cookie (so JS in web application can read and use it)
When REST call is being make cookies are passed. At Controller, token is extracted, checked for expiration, query is done to database to validate token and get user id.
Based on user id, REST will be permited or blocked.
Is this the right approach to implement? I have a pretty big mess in my head after reading articles about spring boot security.
At least: session auth will not work for me (REST is stateless). I want to make auth for mobile device without storing login/password there.
Does it make sense to pass this token in the REST body itself? What in case of GET method?
Many thanks for sharing your knowledge.
Did you find a solution to your problem?
I have answered this problem elsewhere, if you are sure you won't want to open up the API to other developers/clients in the future (if you do then you should look at OAuth) then a simple token based solution will work.
Something basically along the lines of this:
Setup a standard html login page, that you can use for user login to the app
setup spring security to return a cookie on sucessful login with an authentication token
in your mobile app, embed a WebView (or equivalent) and load this login form - allow the user to login via that webview, on response grab the cookie and store the token (as mobile is generally single user, you can keep that pretty long to save mobile users having to keep logging in)
Add a security filter to the the REST API to authenticate against the token (from the mobile app pass the token in the header for example) - then you will be able to use normal spring authentication context for current users etc.
This approach is suggested by Google here: (EDIT: Google seems to have changed the page I originally read to be about using Google+ sign in and OAuth2.0 - I can't see a link to their general Mobile/API docs so here it is in the web archive :) )
I have also written up my implementation here:
Overview of the approach using Spring security
The code & details
Although this was really just an experiment/Proof of concept, it might be useful in your thinking.
Cookie approach seems perfect for the use case. Token can be tied up with user id. Filter can extract cookie and pass user id for example as header to apis - that should take care of GET...

GWT : How to prevent client-side state from being cleared when a redirection (for e.g : OAuth2) happens?

I am implementing OAuth2 authentication for one of my GWT projects (let's call it GWT-app). The application responsible for authentication is a third-party application based on Spring Framework-3.1.2.RELEASE and uses its OAuth2 implementation included in Spring Security-3.1.3.RELEASE (let's call it OAuth-app).
GWT-app is a management application for managing user and stores. Each user has one or more manager accounts. A manager account may have one or more stores attached to it so that he can manage them altogether from one screen of the GWT-app.
It means that the user may potentially have to authenticate many times through different manager accounts to display stores by manager account on the app.
So on the StoreManagement.java page of my GWT-app, I have the following :
private final Map<String, ManagerAndStoresProxy> managerAndStores = Maps.newTreeMap(Ordering.natural());
after authentication, this map should be populated with Manager name and a List of attached stores for each.
OAUTH2 FLOW
The Authorization-code flow is used for authentication. When GWT-app wants to authenticate someone, it redirects the user to a login page on OAuth-app. The user enters his credentials and will be presented with an authorization page asking him whether he wants to allow GWT-app to access his information. If the user clicks on authorize, he is redirected back to the GWT-app with an access token.
THE PROBLEM
The only issue is that since GWT-app is redirecting the user to another application for authentication, the first time the authentication works and the map is populated correctly but if I have to authenticate another account then the previously authenticated account is cleared and can not be retrieved because of the redirection.
The question is then : how can I proceed to persist this map and retrieve it back when a second (third, fourth and so on) authentication flow is over (i.e after the url-redirection of OAuth-app).
WHAT I HAVE TRIED SO FAR
What I did so far is that when the user wants to proceed with authentication from the StoreManagement.java page, he is presented with a popup redirected to the OAuth-app authentication page. The access token is then retrieved from this popup but I have to send it back to the parent window (i.e StoreManagement.java page). This can be done via a HTTP GET parameter but this method reloads the parent page and the result is the same: the previously authenticated account is cleared.
QUESTION
What is the best way to handle this situation without clearing the previous context and without requiring any server-side session mechanism whatsoever ?
The root of the problem is using the authorization code grant; the implicit grant (aka client-side flow) would be a much better fit.
If your app is not limited by old browsers in terms of compatibility then you can try to store all necessary things in HTML5 Web Storage.

Possible approach to secure a Rest API endpoints using Facebook OAuth

I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.