I have a web app that is using the Power BI Web API to display some dashboard data, inside another application. I have followed the authentication examples on GitHub, and can authenticate and query the API.
HOWEVER, all of the examples store the returned tokens in temporary storage (e.g. session), which means that the user has to re-authenticate the application every time they visit (or the app pool restarts).
Ideally, I want to authenticate the web app when it's set up (using a set of credentials set up just for the app), and then have the web app continue to use the same credentials, without the site users having to log back in to Power BI again (as many of the users of the web app do not have direct Power BI access).
Is this possible? If so, how might I go about it? All of the examples I can find are such that you have to re-authenticate every time you access the API. I suspect because I don't know the correct terminology here (this is my first time using the AAD services and authentication) I may be missing something obvious.
To do what you want, you need to securely store the refresh token. The call to get the initial token should return both the accessToken (that expires within 1hr usually) and a refreshToken that you can use to get new accessToken. The refreshToken is usually valid for 90 days, so your access is not indefinitely. There's documentation on MSDN for how to do that:
https://msdn.microsoft.com/en-us/library/ff752395.aspx
Related
I'm trying to implement Google authentication for my app and the below is the workflow I'm trying to set up.
First, user will authenticate with Google and obtain an access token.
User will make requests with this token to backend services.
Backend services will check with Google to validate these token
Once validated, backend services will send information requested by client back to users
And I have a couple question around it:
Is this the correct way to implement it?
How to avoid check with Google for every single request between Backend and Frontend?
It's sort of the correct way. It depends on the details. If I understand correctly, you are in control of the front and backend (these are both your applications). If this is the case, then you would rather use Google services only to authenticate the user (so use an OpenID Connect flow to get an ID token to verify the user's identity). After that, you would have your backend either issue an access token or establish a session with your frontend. Then you wouldn't have to ask Google for the token's validity every time someone makes a request to your backend.
An access token that you get from Google, Facebook, etc. is meant to be used with their APIs. You could use it to authorize access to your own backend, but you then have to call Google on every request to verify the token. You are also tightly coupled to Google's details of the access token usage — what scopes are available, what data is returned with the token, expiration times, etc.
If the access token is a JWT, then you can verify it on your own in your backend. You don't have to call the issuer every time. But, if I remember correctly, Google issues opaque tokens, so this is not the way to go here.
To sum up. If you're in control of the front and back end, then authenticate with Google, then start a session between your applications. This will be simpler to maintain and also safer, as you wouldn't have to handle tokens in the browser.
I have a progressive web application that needs write-access to the Google Drive API for uploading data (media files) the user is creating (either online or offline) in the background while online. It does not really need a server (except for serving the required files, so a static server is sufficient), all of the work could be done on the web application client side.
Since uploading needs to happen on the background, whenever the user is online again (using a service worker and the background sync one-shot API), an access token is not enough for my need (the user can be offline/not use the web application for days) and a refresh token is not supposed to be stored on the web application client side, as far as I understand. Even if it were, I would still need the client secret, which means I have to use a server (or keep the secret within the web application client side, which is a no-no) in order to refresh the token.
It seems like the current ways of using the OAuth2 scheme are at odds with server-less progressive web applications, or I might be missing something. Progressive web applications are more like Chrome applications in this regard, I guess, but I have to supply a Chrome application ID in the Google API console for my application, which I do not (and do not intend to) have and Chrome applications use the Chrome identity API for getting the tokens, which I do not intend to use (and cannot).
I am currently using an actual Node.js server which takes care of the authorization step, keeps the access token and refresh token in a database and returns the existing or new access token to the client, whenever asked. The server is redundant here (and requires a privacy policy for this data which I really do not need to store), I want to do everything using client code, without continuously asking for authorization whenever I upload in the background.
Keeping the refresh token on the web application client side and just reaching out to the server for actually refreshing the access token (nothing must be stored in the server side except the client secret, which is fine), but like I mentioned, I understand the refresh token is not supposed to be kept on the web application side.
Is there a safe and secure way to implement this without a server (or with a server that only gets the refresh token and returns it to the client and refreshes the access token by getting the refresh token from the client)?
It's actually fairly simple, depending on the fine details of your use case.
An important factoid is that once a user has granted permission to your app, he will not have to re-grant it. So you don't need to "continuously asking for authorization whenever I upload in the background". However, the only constraint is that the user must be logged in to Google in order to obtain an Access Token. Normally this isn't an issue, but your app needs to deal with the scenario that a user has logged off from Google, and prompt for login.
All the details are here https://developers.google.com/identity/protocols/OAuth2UserAgent
I suggest avoid the Google JS library because (a) it has its own opinions about the UX, (b) wasn't written with PWAs in mind, (c) has issues on mobile, and (d) is closed source so when it breaks (as it does occasionally), your users are dead in the water until Google fixes it. The page above details the OAuth endpoints so you can easily use them directly. This has the side benefit that adding other cloud storage accounts (AWS, Azure, Drop, etc) is just a case of changing the endpoint URL.
The architecture I use in my PWA is to have my PWA prompt once (and once only) for authorization and then store the user's Gmail address in localStorage. I then have a
hidden iframe which polls once per hour for an Access Token, using the gmail address in a login_hint. This means the iframe is never required to present any UX. The only time UX is required is for the initial auth, which is of course unavoidable, and once per session if the user has logged out of Google.
The only other edge-case you might want to deal with is allowing the user to select between multiple Google accounts, say a personal account and a work domain account.
On a broader point, remember that Google didn't create the OAuth spec so there is little they can do to provide an alternative solution. At an abstract level, auth requires one of the user being present, or secure storage for a permanent token (eg on a server or within a secure store such as Android). Even if we invent OAuth 3, that will still be the case.
I have a question more related to the way OAuth 2 is working but since using IdentityServer to implement OAuth I think it's relevant. I could not find an answer anywhere.
I'm building a website and a mobile app that consumes my own API. Each user of my app will have a username and password, that will give him access to the app/website and though the API to his information.
I'm not sure about the right way to handle the flow for user login:
On the website I have my own designed login form. I don't want to move the user to my auth server to login, and then have him approve the information he gives - he is the user on my system - I have access to all information - kida like facebook has a login and access to the informatio - they don't ask what you're willing to give them. So is implicit really the way for this?
On the mobile app I also have a login form and now I read here (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-10) that the OAuth approach is to have the login in a WebView?? Doesn't look like facebook login is in a WebView on their mobile app.
The approach I was first lookin at is the Resource Owner. Users will login, get the token and the refresh token and can start working against my APIs. But storing my client_id and secret on the mobile app? on the website javascript files? doesn't feel right. I can of course make a call to an API that will mask those and be a proxy to the login process... but... (read #4).
In the future I would like to allow access for third-party developers. For them to allow login for users of my system I will use the implicit flow. Also, I plan for those developer accounts to have restricted API access (for example, the number of calls to the API will be limited by plan). What prevents those developers from asking for the username and password of their account on my system on their website, getting the response from my servers with the access token and refresh token, and using my API however they want, without restrictions, and having access to the entire user profile?
Lets say I'm sticking to the resource owner flow, receiving back from the server a token and a refresh token. What should I store on the mobile device and how? What should be stored in the browser and how? the refresh token? and each time he opens the app get a new updated token with that refresh token?
Edit
Just to clarify, because I find a lot of lectures and articles that explain the process from an API consumer point of view (ie. the third-party developer): I am the API owner and the auth server owner, I'm the owner of the user accounts (they are my users of my services), I'm also my own consumer (though the website and the mobile app), and in the future I want to enable third-party developers to allow my users to login with their accounts of my service (kinda like Facebook or Google)
You're correct that you shouldn't store the client_secret in your app, but I doubt you will get around storing the client_id. You could disable the consent screen for your app as well, and build a native login view. You need to store the access_token and the refresh_token on the device (maybe encrypted in a database) if you don't want the user to login everytime they use your app.
As for problem 4, you could do the following:
Embed the client_secret in your (web) app
Set up which hosts have access to your api on the IdentityServer
The IdentityServer generates a salt and sends it to the client
The client calculates a session_secret using hash(ip_address + session_salt)
The client uses the session_secret and the client_secret for the API call
Server validates the hash and client_secret
It's nearly impossible to completely prevent someone from using your API. But you should add various rate limiting methods, such as limiting IP addresses, API calls etc. But nothing will stop someone decompiling your app and accessing your client_id.
I am creating a node based authentication server for Google that my apps can use to get access tokens for google data apis.
I am basing this off the server side flow as described here: https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps
I am at the point where I am trying to implement the refresh token logic for when a token expires. For this I obviously need the refresh_token. I get the refresh token no problem - the first time that I access the service but subsequent times I do not.
I plan to keep these tokens in local storage on the browser so it's generally not a problem - until I access the same service on my mobile or any additional device.
How do I get a refresh token on a second or third device?
Surely I don't have to revoke the tokens and sign in again each time I want to switch to a new device?
Thanks
We are trying to integrate TripIt with our web application for itinerary management. I created a new App and got api key & secret. But we want to use the employee's trip it account and retrieve their trips & create trip in their account. Now i have one dilemma, since i am using my api key & secret, i can able to retrieve trips created in my account, but i want to retrieve trips of whoever logged in with their tripit account, with my api key.
So in this scenario, i will ask for user's trip it credentials and is there a way i can get their trips using my api key? Any viable solution is welcome. If you clear me with the flow i can able to understand.
The (OAuth) API key and secret are issued for your application, not for your specific user account. What this means is that your application can be given permission to access the user's data. If you've ever worked with the Twitter or Facebook APIs, TripIt's API behaves much the same.
You register an application through TripIt (sounds like you've already got this step down)
Using an SDK of your choice, you create endpoints in your code to handle the various steps in the OAuth workflow.
Here is a quick rundown of the workflow for OAuth 1.0, which TripIt uses.
The user begins the process of connecting their TripIt account to your application
Your application builds a request token URL and sends the user to TripIt's OAuth dialog, indicating the callback_url
The OAuth dialog (on TripIt's site) prompts the user to accept or decline permissions
If approved, they return to your site (callback_url) with a 'signed' request token as part of the query string
A backend process, typically a simple CURL request, exchanges the request token for an access token to finalize the process
You store the access token associated with the user in your database and use it for future requests against the API
If you happen to be using PHP, here is an open source example application to take a look at. It does not save the token to a database (just keeps it in the session), but you should be able to glean the basic idea from it.