We're trying to create an easy auth flow in our app to manage multiple user's Google ads campaign data. We would like to get the permissions via javascript popup on the client app and then use the token to make updates.
Would somebody have a code example of how to do this? Also a description of best practice flow.
The actual updates to the campaigns can happen client side or server side if there's limitations with the api on the client side, but the authorization should happen client side.
Related
I am building a website using .net. The plan is to use the strava api to get activity data of the user.
Currently the user will need to accept this strava prompt every time he reloads my site:
I got the auth flow working but my question is how to keep the user logged in. If I only store the tokens on my server I won't recognize the user on reload (or I have to use separate authentication). However if I store the tokens on the client the user will be able to make requests to the strava api on behalf on my application.
I tried to add custom jwt authentication to my server but don't like the complexity this is adding. I want to avoid it if possible.
Which of these is the standard way of doing it? Or is there a different strategy I am not seeing?
When reading the doc of google oauth API, I found that it does not offer refresh token to Javascript (JS) web app, as mentioned in below link. It says "Refresh tokens are not typically used in client-side (JavaScript) web applications."
https://developers.google.com/identity/protocols/oauth2/web-server
However in the following page it offers the refresh token (as well as client secret) to native app. Seems strange that both JS web app and native app are not confidential. Shoudn't it also not to offer refresh token and client secret to native app?
https://developers.google.com/identity/protocols/oauth2/native-app
Thanks
A refresh token in a client sided application where anyone could view source and see the refresh token and client id and client secret. This would mean that anyone could then create a new access token to access the data.
If I understand what you mean by native apps they are run on a users machine and there by the only one in theory who would be accessing that machine would be the user who is accessing their own data. Native apps can also better protect the various secrets from both the user and other apps. So while it is still an exposure risk - the risk is significantly lower.
Use a server side web language if you want a refresh token.
I have a single player Unity game which records stats about game run-throughs, such as accuracy/runtime. I want these stats to be saved onto a web server / db so I can later aggregate them, the web server being a Node app using Express and the DB being a MongoDB instance. I have made the API routes to POST/GET the data but at the moment the routes are public. Normally, I would implement JWT whereby the user would have to login to be able to make web requests, but since the game is single player there is no login credentials to use.
What would be the best way to verify that a call to my web service has been made from within the Unity game without requiring the user to login/register an account?
So far I have thought about using a key on the Unity-side that needs to be sent through with each request, but this is prone to being discovered by searching through the source code.
Implement oAuth on top of your REST API on the Node side. Now a caller has to provide an access token when calling your API. Make sure your implementation supports a flow you're going to choose in step 2. oauth2authorize is a popular toolkit.
Choose an appropriate oAuth flow and implement it on the Unity side. One possibility is the client credentials grant, a flow designed for service-to-service calls. Another option is exchanging JWT for an access token; the payload of the JWT can reflect the security context of the caller being the Unity game itself.
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.