What is the best approach for authentication flow in PWA when its offline. I am using OIDC client js for online authentication flow.
The Authorization Server sits alongside your APIs so I would treat both the same:
If the device is offline you cannot call your APIs so you have to use data that is cached locally - such as that for the last rendered view
If the device is offline you also cannot perform user authentication or token refresh operations
Nothing about OIDC behaviour would change - you just need a design pattern for API access, which does not really depend on the technology you are using:
MyView uses a MyApiClient
When online, MyApiClient initiates OAuth related calls if there is no token yet, then adds a token to the Authorization header and calls MyApi
When offline, MyApiClient looks in a local cache instead and displays cached data if it can, while also informing the user they are offline
Related
Consider that we have:
An SPA or a statically generated JAMStack website.
A REST API.
The website is being served with nignx that also reverse proxies to our API.
--
It is required that a user should be able to register/authenticate with an identity provider (say, Google) through the OpenID Connect protocol. For the sake of simplicity, let us assume that the user has already registered with our API.
Talking about authentication using OIDC, from what I have read on the subject, the steps you take are the following:
Register the application with the IdP and receive a client id and a secret.
When the user initiates a login (with Google) request on the API ('/api/loginWithGoogle') the API sets a state variable on the request session (to prevent CSRF) and redirects the user-agent to the IdP's login page.
At this page, the user enters their credentials and if they are correct, the IdP redirects the user to the callback URL on the API callback (/api/callback).
The request received on the callback has the state parameter (which we should verify with the one we set on the session previously) and a code parameter. We exchange the code for the identity token with the authorization server/IdP (we also receive access/refresh tokens from the auth server, which we discard for now because we do not want to access any APIs on the behalf of the user).
The identity token is parsed to verify user identity against our database (maybe an email).
Assume that the identity is verified.
-- The next part is what's giving me trouble --
The documentation that I have read advises that from here we redirect the user to a URL (e.g. the profile page)and start a login session between the user agent and the API. This is fine for this specific architecture (with both the SPA/static-site being hosted on the same domain).
But how does it scale?
Say I want to move from a session based flow to a JWT based flow (for authenticating to my API).
What if a mobile application comes into the picture? How can it leverage a similar SSO functionality from my API?
NOTE: I have read a little on the PKCE mechanism for SPAs (I assume it works for JAMStack as well) and native mobile apps, but from what I gather, it is an authorization mechanism that assumes that there is no back-end in place. I can not reconcile PKCE in an authentication context when an API is involved.
Usually this is done via the following components. By separating these concerns you can ensure that flows work well for all of your apps and APIs.
BACKEND FOR FRONTEND
This is a utility API to keep tokens for the SPA out of the browser and to supply the client secret to the token service.
WEB HOST
This serves unsecured static content for the SPA. It is possible to use the BFF to do this, though a separated component allows you to serve content via a content delivery network, which some companies prefer.
TOKEN SERVICE
This does the issuing of tokens for your apps and APIs. You could use Google initially, though a more complete solution is to use your own Authorization Server (AS). This is because you will not be able to control the contents of Google access tokens when authorizating in your own APIs.
SPA CLIENT
This interacts with the Backend for Frontend during OAuth and API calls. Cookies are sent from the browser and the backend forwards tokens to APIs.
MOBILE CLIENT
This interacts with the token service and uses tokens to call APIs directly, without using a Backend for Frontend.
BUSINESS APIs
These only ever receive JWT access tokens and do not deal with any cookie concerns. APIs can be hosted in any domain.
SCALING
In order for cookies to work properly, a separate instance of the Backend for Frontend must be deployed for each SPA, where each instance runs on the same parent domain as the SPA's web origin.
UPDATE - AS REQUESTED
The backend for frontend can be either a traditional web backend or an API. In the latter case CORS is used.
See this code example for an API driven approach. Any Authorization Server can be used as the token service. Following the tutorial may help you to see how the components fit together. SPA security is a difficult topic though.
I am making a REST server which will have both the web clients in form of Single Page application and in form of native mobile applications. I was studying about using JWTs to make server stateless.
Till now what I understood is :
The authentication Endpoint returns two tokens , i.e., access and refresh token after providing the correct credentials.
These Tokens should be stored in a 'httpOnly' cookie on a browser for security reasons.
As far as I know Native Mobile applications don't have cookies store and hence they have some other datastore for an application such as database. So, do I need to implement two different endpoints for these different applications? What I am thinking to do is:
Endpoint 1 (For Single Point Application): Accepts user credentials in json and Returns jwt inside cookies
Endpoint 2 (For native mobile applications) : Accepts user credentials in json and Returns jwt in raw json body.
Is the above approach right or do we have a single endpoint for both of them. Also do help how to achieve this with django-rest-framework-simplejwt.
You shouldn't need to create two different authentication views for SPAs and mobile apps. On mobile, you'll just need to store both the refresh and access tokens on the device somehow whether it's in memory or on disk or whatever. But you'll get the tokens from the same view either way. And then you'll need to include them in the Authorization header with any requests to your API that require authorization as described in the docs here: https://github.com/davesque/django-rest-framework-simplejwt#usage
I am trying to implement the Authorization Code flow described in RFC 6749 (OAuth 2.0) for a JavaScript-based application. I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end. Then all requests from the front-end to any protected resources go via the web server back-end, which attaches the access token to the request and proxies it on.
My question is how do I let the JavaScript front-end make use of these tokens in a secure way? I assume that I have to do something like set up a session on the web server and pass back a cookie that identifies the session. But this means that the JavaScript application then has a cookie that gives them the same privileges as if they just had direct access to the bearer tokens stored in the web server. How does having a web server to hold the tokens give extra security?
I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end.
No, it is a misunderstanding of the OAuth2 flows and goals.
Here is the OAuth2 main goal: your application (which can for instance be a JavaScript program running in the browser, a web server, both, etc.) MUST NOT need to know the user's credentials (most of the time a login/password pair) to access the service on behalf of the user.
Here is the way OAuth2 must be used to achieve this goal:
according to your needs, that is having a Javascript-based application running in the browser (i.e. not a node.js application), you need to use the OAuth2 implicit flow, not the authorization code flow. But of course, because your application is running in the browser, it will not be able to persist the credentials to access the resource offered by the service provider. The user will have to authenticate to the service provider for each new session on your application.
when your application needs to access the service provider when the user is not logged in, or when your application is able to persist credentials (because your application has its own credential system to identify its users), your application does not only rely on a JavaScript program running in the browser. It may rely only on a web server, or on both a web server and a JavaScript program that talks to this server. So, in those cases, you must use the authorization code flow.
So, as a conclusion, you have decided to add a web server to your application because you thought you had to use the authorization code flow. But in your case, you probably do not have to use this code flow, therefore you should select the appropriate code flow for your application: implicit code flow. And this way, you do not have to add a web server to run your application.
How does having a web server to hold the tokens give extra security?
This does not give extra security. Having a web server to hold the tokens is simply a way to let your application access the service on behalf of the user, in the background, when the user is not logged on your application.
While I agree with Alexandre Fenyo's comments, I just want to add the 2021 version. You should no longer be using the implicit flow as this is no longer considered secure.
For scenarios such as this where a JavaScript application has to handle tokens I would suggest using the Authorization Code flow with PKCE instead: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
I have a set of REST APIs that are secured by oauth 2. I need to access them from an Android app and a webapp.
Accessing the APIs from android app seems pretty straight forward for me to implement. What I am unable to understand here is - what is the correct and secure way to access the same APIs from a webapp?
I am thinking, I shouldn't be making any direct calls to the APIs from the browser, using some JS library, for it seems to me that it would be pretty insecure. Instead, I should keep it all traditional, by submitting requests to the web server and then letting it make the REST API call. This would be similar to the method of making REST calls from Android.
Am I correct in my thinking/approach?
Accessing your API should be the same no matter where the request is coming from. You just use an Authorization header with bearer scheme and stick the JWT token in there.
The way you get the JWT token is different though, as I explain in this answer. It all depends on how much you trust the client application.
If your client is a web application that queries your API from the server side, you can use the code authorization grant and get an access and refresh token for your API.
If you want to access your API from a JavaScript application, you have no way to hide app-keys or refresh tokens, so you should use the implicit grant.
If you know how to store secrets securely on your Android client, you could use the resource owner password grant.
The code authorization grant is definitively the most secure as it's much harder to compromise a server application than an application that runs on your machine.
Using OAuth 2 I need to limit user access to permitted resources only, where the connection to the API is made through an ext.js REST proxy. The ext.js proxy takes care of data retrieval and maintaining the model relationships. I haven't found an elegant way to make different calls from the proxy to the backend depending on the user logged in.
I am wondering if the proxy has to be different for each user logged in to my application because each user has their own access token.
Another option would be to make the proxy know about the logged in user during the proxy initialisation process and save this information in a persistent way.
Has anyone solved a similar situation before?
The article gives a detailed explanation on how to use OAuth2 with Sencha Touch.
http://www.sencha.com/blog/meetcha-using-sencha-touch-to-build-a-mobile-app-for-meetup-com/
There are several ways to use OAuth. One uses redirects after the initial authentication (for this you might use an iFrame inside a Sencha login view). The other uses your backend server as an intermediary to the OAuth server that can avoid the iFrame solution but requires more logic on your server.
You can then use a session cookie which will be resent with all HTTP requests including your REST calls. Most back ends support session cookies and so all you need to do then is look up the user ID you stored in the session object as part of your REST API code.
Another option is to set a custom HTTP header in each REST call that requires authentication. To avoid duplicate code, create a derived class from the Sencha proxy class to set the header containing the access token. You can store the access token in a Store or on the Application object or as a static value on the proxy. I've done this for both REST proxy calls and Sencha Direct proxy calls.
AJAX Proxy header property:
http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.proxy.Ajax-cfg-headers