Does OAuth 2.0 always require a browser in the flow - security

Can I use OAuth 2.0 without a browser (or an embedded browser in my app) to perform nightly uploads?
Setup I have a refresh token and access token from provider console-- Google Drive API
I wish to use Java SDK to use/reuse these to upload data without the requirement for any browser authorization once i have initially received my refresh/access tokens.

OAuth 2.0 requires a browser for user consent once
A browser is required, so that the user can agree to the request of the app to access the users data.
After the user agreed on sharing the data with the app, the app can use the refresh token without a browser based flow.
Documented here: https://developers.google.com/accounts/docs/OAuth2WebServer
Alternative for non-browser apps
You may use the OAuth 2.0 for Devices flow:
You app can act as a device which queries a code from google, displays it to the user, and asks the user to browse to a verification URL (e.g. with (system.out.println...).
So a browser is still needed, but your application itself doesn't need to provide a webpage to the user.

Yes. That is precisely what unattended access with the refresh token is about. When the user granted permission to the app, he was specifically prompted "... even when you're not logged in" (or similar, I can't remember the exact wording). You will store the refresh token on the server somewhere, and then use it to request an access token whenever your app needs to do its thang.
Just to clarify some of the wording in your question, the refreash and access tokens do NOT form a pair, so saying "reuse these", should actually be "reuse this", where 'this' is the refresh token.

Related

OAuth2 process and best practices for private apps

Please bear with me while I explain my problem and the solutions/guides I have found.
Description: In my company, we have one product that have multiple modules. Each module is its separate backend and frontend. We have JavaEE/JakartaEE with JAX-RS as our backend stack and React as for our frontend. Until now we are using Basic Authentication using the JavaEE Security via Sessions, but because the product is evolving and we need mobile clients and allow third parties to access the data, we have decided to integrate OAuth2/OpenID Connect into our application.
Since there are multiple implementations out there that provide OAuth2 functionality, we are currently looking into a few available options. (Keycloak and ORY Hydra for example). The decision which we will choose depends on how much work we want to do change the existing structure of the application how we handle the users in the database. But regardless of which implementation we opt for, we have similar questions going forward.
Questions
How do the react applications handle login process and token storage?
Every documentation says: If the user is not logged in s/he is redirected to the login page. Where after login and consent he is redirected back to the app (After completing the oauth2 workflow obviously) with the Access/ID Token for the resource server and/or Refresh Token for refreshing the Access/ID Token.
Now here is what is not clear to me:
Since this is our own React app, we do not want to show the consent screen, like in apps from Microsoft/Google etc you do not see any. I guess this is possible by setting a value in the request itself, or skipping the consent screen based on the client id but I just want to make sure.
Next is where do I store the Access and Refresh Token? Access Token should be sent as the Bearer token with each request. So it can be stored in local storage because they are short lived, but the refresh token should be stored securely. Like in a secure http cookie?. If that is the case, then the server has to set it. If this is correct is this how the flow will look like?
Our React App (Not logged In) --> Login Page (Another React Page) --> User Enters Credentials --> Java Backend --> Authenticates the user --> Initiate the OAuth2 process --> Get the Access and Refresh Tokens --> Set them as secure Cookies --> Return the authenticated response to frontend with the cookies --> Login Page redirects to the previous page --> User continues with the app
This does not feel correct. How would PKCE help in this case?
Assuming what I wrote above is correct, I would need different login flows when the users logs in from our own app or from a third party app. That can however be determined by checking client ids or disabling password flow for third party clients.
The same would be applicable then for the refresh token flow too. Because for my own app I have to set the cookies, for third parties this has to be directly from the OAuth Server
Resources I have read/researched:
https://gist.github.com/mziwisky/10079157
How does OAuth work?
Edit: Adding more links I have read
What is the purpose of implicit grant
Best practices for session management
RESTful Authentication
And of course various writings and examples from Keycloak and ORY Hydra also.
I am currently trying both Keycloak and ORY Hydra figuring out which fits our needs better.
Thank you all in advance!
You don't have to show the consent screen. Here's an example of a React app authenticating using the Authorization Code Grant: https://fusionauth.io/blog/2020/03/10/securely-implement-oauth-in-react (full disclosure, this is on my employer's site but will work with any OAuth2 compliant identity server).
The short answer is that it's best for you to avoid the implicit grant, and have the access and refresh tokens stored in some middleware, not the browser. The example in the link uses a 100 line express server and stores those tokens in the session.
I wrote a bit about PKCE. Excerpt:
The Proof Key for Code Exchange (PKCE) RFC was published in 2015 and extends the Authorization Code grant to protect from an attack if part of the authorization flow happens over a non TLS connection. For example, between components of a native application. This attack could also happen if TLS has a vulnerability or if router firmware has been compromised and is spoofing DNS or downgrading from TLS to HTTP. PKCE requires an additional one-time code to be sent to the OAuth server. This is used to validate the request has not been intercepted or modified.
Here's a breakdown of the various OAuth options you have (again, this is on my employer's site but will work with any OAuth2 compliant identity server): https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows You can allow different flows for different clients. For example, you could use the Authorization Code Grant for third parties and the Resource Owner Password Credentials grant (which essentially is username and password) for your own applications.
I'm not sure I answered all of your questions, but I hope that some of this is helpful.
The OAuth 2.0 Security Best Current Practice should be consulted. Even though it is still a "Internet Draft" it is mature and has been implemented by several vender implementations.
In general the OAuth 2.0 Authorization Code with PKCE Flow is the recommendation regardless of the use of Bearer tokens or JWT.
You should also consider reading about WebAuthn (Where there is not password)

Security concerns about using Facebook implicit token for server side resource server OAuth2 authentication

I have poured over the OAuth2 docs and seen how the Facebook Javascript SDK uses Implicit Grant.
I am building a ReactJs application, which communicates with a PHP-Symfony API.
What I want to do is offer the "Login with Facebook" option on the frontend.
What I need on my PHP server is the Facebook user id and email and other data of the user so I can initially create a user record for them in my DB and then on returning visit, use the auth token to get that info again on the server and use it to match it to existing records and log the user in.
We have done this previously using the Authorization Code Grant method to redirect the frontend to our server, then to facebook and then back to us with the auth code. We then use that on the server with our Secret Key to get the Access Token and get the user info directly from Facebook to our server and then authenticate the user.
The redirection is a bit of a pain for a single page application.
Facebook's Javascript SDK handles a lot of that automatically, but uses Implicit Grant, returning an Access Token directly to the frontend.
What I want to know is, can I just send that Access Token to my server to do the same type of authentication that I did before? Or is that a massive security hole that I am opening up?
Comparing the two, the Auth Code from the Authorization Code Grant flow also goes via the frontend, but very quickly, not directly to JavaScript and is much shorter lived. So it feels much more secure.
If intercepted in time and with matching state, it could be used to authenticate someone on our server, but not access someone's Facebook data directly.
Reusing the frontend Access Token from the Implicit Grant flow feels like it is open to messing with, but I can't put my finger on the exact scenario that would make it more vulnerable to attack. The token would potentially give people access to not only authenticating on our server but also to accessing people's Facebook info.
So this is ultimately a question of best practice and security.
We think that we should be able to implement our own popout window that does the Authorization Code Grant style flow and retrieves our server cookie which can then be used by the page that spawned it, but it is going to be tricky and most of the work seems to be done for the Implicit Grant method, if it is safe to use as we intend to use it.
Best Practices AND According to the RFC 6749
However, this convenience should be weighed against the security
implications of using implicit grants, such as those described in
Sections 10.3 and 10.16, especially when the authorization code
grant type is available.

Login App with IdentityServer4

I have to develop a SSO system and I have to do it using IdentityServer4. I have gone through the documentation and examples but I have some doubts. To be honest I don't quite get it, but I am really new in Oauth2 and OpenId Connect.
We will have a bunch of clients (web apps), each of one of those will have their own Web APi. And we have to have a centraliced Login App for all of those. I think the example with the javascript client is the closes to the thing we want to achieve. Also, a user might have permission to access one client (app), but not another, so the IdentityServer must provide information about wich clients (apps), that particularly user can access.
So, These are the things I don Understand:
1.- In the documentation I can read there are two tokens, an Identity Token and Access token. But in the examples all I see are the access tokens. It seems to me that the access token is the one with all de info needed. am I wrong?
2.- Also, I have read about de Grant Types and I'am not quite sure wich one we must use. At first I thought to use the ResourceOwner password, because it requires the client, the secret, a user and a password, wich I assumed it could be the end user. I found this example http://sunilrav.com/post/How-to-Customize-Authentication-in-Identity-Server-4 were one could customise the class that validate the user and password. I thought that this could be the way to go but the documentation statesa about this grant type "...This is so called “non-interactive” authentication and is generally not recommended.". The javascript client example uses the implicit Grat type, wich the documentation states is for browser-based applications (our client apps will all be browser based using react).
3.- can my Login app be a Javascript (react) app? The example Quickstart is made in MVC.NET. This login app connects directly to de IS4 server without asking for a access token? (In the example the app is embebed in the IS4).
4.- Can I protect with IS4 a WEB API which is developed in .net framework (4.6.2) and not in .Net Core? I havent Found Any examples.
the documentatios I followed is the offcial. The examples (quickstart) are also there. (I can't post more than two links).
thank you very much for reading and for your help.
Identity Token and Access token
Identity token is the one that contains the identity of the user, that will tell the client app that what user it is. After successful login, user will be redirected to the client app with these tokens. Response will also have claims, such as permission scopes, name , email you can add custom claims as well.
Access token is used to access your protected web api resource. You have to send the access token with each request to access the api.
Grant Types
Grant types is basically how you want your client app to interact with the auth server. https://identityserver4.readthedocs.io/en/release/topics/grant_types.html
can my Login app be a Javascript (react) app? Your client app can be a javascript app but your auth server that is the identity server which will have the login/signup pages(and other login jazz) and account controllers should be you MVC app. As, everything is already done using MVC and Entity framework, why you want to re do everything.
Can I protect with IS4 a WEB API I am not sure about this one, but I dont see why you would not be able to do it.
This is a good answer for basic IdSrv flow!
UPDATE In my understanding, the answer to which Grant Type to use it depends on your client application requirement. If you want to use a Javascript client you can use Implicit Flow, but you won't be able to use refresh tokens and your access token is not 100% secured with the browser as client can access it.
If you want to open your web api to public then you can use client credentials flow. If you want to be more secure you should use Hybrid flow or HybridClient credential flow. ( again depends on the requirements ). with this you will be able to use refresh tokens and in this way your access token would be more secure.

Authentication strategy between my chome extension and server

I'm in the process of building a Google Chrome extension, and have some questions about how to implement security into the application.
I need to access a couple of Google API's so am going to be using OAuth 2.0 for that. So basically from the extension I know which user is logged into the browser.
My extension then needs to get and post data to my (nodejs) API service. I want to ensure that the user requesting data is the same user that is logged into the browser. Is there any way of using the previous Google authentication process to also authenticate communications between the extension and my API? I dont really want the user to have to log in again, to access my API.
I'm sure I'm missing something simple, and I've not been able to find anything that fits this scenario
Follow the OpenID Connect auth flow and you will get an access_token and an id_token. The acess_token you will use to use to make authenticated requests to Google APIs as usual. The id_token will be used as authentication with requests to your server.
When the requests hit your server you will need to validate the token and you can then use the contents of the id_token to identify the user.
User wouldn't have to login on auth process provided if user is already logged in and you are using a web application flow (not chrome.identity APIs) but user would see the consent screen atleast the first time. However you can skip the account selector screen if you already know the email address by providing &login_hint= parameter.

cross site authentication which is compatible with OAuth 2.0

In my case, company B (domain B) hosts a portal, which has link to my web app (domain A). If user clicks on hyperlink on the portal to my domain, he/she should be automatically logged into my app.
Existing poilicies that i cannot change:
User also has the ability to log into my domain directly, without going through the portal by supplying user id/password.
Also, existing company policy for user provisioning is that even if user log through portal of company B, they first need to have a user account with my company. Hence, the user will have account with portal company and my company.
Given these constraints, my plan for is following to provide automatic login from the portal.
When the user logs in to the portal, the portal company will generate a temporary token (UUID) and attach it as a query parameter to the hyperlink to my web app. When user clicks on my web app's hyperlink, my web app will receive a GET/POST request on the server side for a protected resource. At the server side, my web app will over https (probably two way SSL) invoke a URL on the portal's side, passing the temporary token. The portal side responds with a user id. My web app will map the user id with user's credentials and create a session for the user and allow access to the protected resource.
When the user logs out of the portal application, the portal server will make an Https request to my web app at a prespecified URL to log the user out. Since it would be two way SSL, logout url is protected.
My questions are following:
Is there a standards based approach to achieving the above scenario. In near future, my company is planning to support OAuth 2.0 and i want to ensure that the above scenario will not violate any OAuth standard. As per my understanding, OAuth 2.0 leaves the validation of the access-token to the implementations. I am hoping that the temporary token described above is sort of access-token.
Once the user closes the portal browser, is it possible for browser to destroy the cookie. In this case, if user opens another browser later on, he/she should authenticate again.
Is there a standards based approach to achieving the above scenario. In near future, my company is planning to support OAuth 2.0 and i want to ensure that the above scenario will not violate any OAuth standard.
You kind of like answered your question already. That "standard-based approach" is OAuth which a Standards Track already documented by IETF in RFC 6749 and has been adopted by many software entities. If you don't implement OAuth then you are not violating the standardisation rules, you will be violating it if you claim to have implemented OAuth authorization in your system which clearly you haven't.
As per my understanding, OAuth 2.0 leaves the validation of the access-token to the implementations.
Well, OAuth is a bit more complex than just generating an access token, there's an authorization grant request involved before you can request an access token. You could also expose a token refresh endpoint if the life span of the access token needs to be extended by the client. So, there's more than just access token requests involved in OAuth authorization process
I am hoping that the temporary token described above is sort of access-token
What's an access token? It is up to you how you implement an access token, the implementation details belong to you and nobody else. The only thing that you need to guarantee is that the access token represents the authorization issued to client and its scope, in other words, given an access token your system should be able to identify a client and the scope of this client...what the client is allowed to do, what resources the client is allowed to request. Be aware that OAuth defines clients which doesn't directly translate to users, it could well be a user, another system, component or app.
Once the user closes the portal browser, is it possible for browser to destroy the cookie. In this case, if user opens another browser later on, he/she should authenticate again
Absolutely, yes. This is not related to OAuth at all, it's up to the client what they do with the access token and how they store it. If your system issues a non-persistent cookie, then as soon as the user closes the browser then the browser session is destroyed and also the cookie. All modern web development technologies offer cookie management implementations such as JSP, ASP.NET, PHP, etc. So I would suggest to store the access token in a non-persistent cookie and have your authorization server inspect requests to all protected resources by checking for the authentication ticket/cookie (where the access token is) and validate the access token, if the access token (or cookie) is not present then reject the request since it is an anonymous request to a protected resource.
Hope it makes sense

Resources