Where to store refresh token using strava api - authentication

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?

Related

Persisting a login with the Slack API

I currently have this flow but I am unsure of the architecture going forward.
On my page, the user gets sent to the Slack OAuth API where they confirm scopes
User gets redirected back to my page with a one time code
Client sends a request to the server with the code
The server sends a request to Slack with the code, exchanging it for an access token
If the code and token are OK, it creates a new user in MongoDB
I made a flowchart to illustrate:
I would like the user to not have to authorize the scopes every time they want to access the service, and even if they did, how would I keep the token around in a secure manner to make requests? Would I have to create my own token authentication with login and password, or is there a better way? Should I persist this token on the client somehow and have the users be logged in that way? If so, what is the best way to do that?
Slack token generation must be one time activity per user.
When creating user in MongoDB, you should also store the generated token securely.
For later use, your application should use the stored token for any slack interactions, given that you have authenticated the user whose token you'll be using.

Workflow to implement Google OAuth2.0

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.

Is there a faster alternative to Auth0 API for requesting a user's profile using an Access Token?

I'm building my authentication manually using Auth0 API's since there is no SDK for SvelteKit at the time I'm writing this question.
So far I managed to get an Access Token, send it in a cookie to the browser and send it back at every request for a check using the Auth0 API for user profiles before passing the request to an endpoint.
The problem is the lack of speed. It takes about 1s to navigate from one page to another in the browser.
I don't think I can keep Access Tokens in memory server-side (due to the nature of SvelteKit) but I want to keep things simple.
Is there an alternative to Auth0 with a faster API?

How to use Google APIs without continuously explicit user consent from a progressive web application?

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.

What is the correct way to use OAuth for mobile and website consuming my own API?

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.