Logging out client side secrets in the user agent (browser) - security

There are sound reasons not to put any secrets, PII or other sensitive information into the logs on the backend side (see OWASP ASVS V7).
But should the same rule apply on the frontend side? Is there a sound reason we should prohibit devs from logging out e.g. jwt tokens into the console in the browser?

Related

Securing NodeJS RESTful API and React client app

I've a backend RESTful API built in NodeJS and a front end application in React JS(NextJS), both hosted on AWS. The client and server communicates using JWT token.
I want to make sure both the client app and server side app are highly secured.
What i've done:
I'm using HTTPS for both client and server
Whitelist the client react app IP address so only the client react app can talk to the server app. This was done in AWS security group
Use cors in my server Node.JS application, to whitelist the client IP address again as an addition to No. 1
Use AWS WAF to secure the backend NodeJS application,
Use helmet in the NodeJS server backend API
Make sure the JWT token only last seven days, it'll be invalid and the user needs to login again to get a new token.
Answers i've looked at and used:
How to secure client app (react) and API communication
According to: RESTful Authentication i'm using Token in HTTP headers (e.g. OAuth 2.0 + JWT), this i sent for every client request
Using a refresh token: Refresh Token Jsonwebtoken
What i'm concerned about, and i need some help with:
1. Since the JWT token is how the server validates the client, is the JWT communication secured? Are there other steps i can take to improve the JWT security?
2. Is this application architecture secured enough?
3. Is there anything else i can do improve it's security, as i'm really concerned and want to make sure it's very secured.
4. Should i encrypt the JSON payload sent from the client to the server? because that's visible in any browser network tab under XHR, i'm sending username & password as payload for login.
I'm mostly concerned about security because i've integrated stripe payment in the application, and i'm also storing some sensitive data.
Any recommendation would be high appreciated, this is my first time deploying an production app.
As of what you have done the application must be pretty much secure.... except i would like to add a few things....
Make sure that the tokens have expiry and use refresh token to issue new tokens. The jwt stored at clients could be vulnerable for man in the middle attack. (For more performance use redis to store refresh tokens... look more on this)
If you are using https, the request will be only visible to the client's browser and not to any sniffers in the network (check on this whether ure able to see encrypted payload in sniffing tools like wireshark etc... to validate the https uve used). So its not necessary to go for any more encryption. That would decrease the performance of the api server.

Which OAuth2 authentication flow shoud I use for PWA + server side application

I am trying to choose the right authentication flow for an application:
Fontend is an Progressive Web App accessible only via HTTPS. It'is done in Angular, Single Page Application.
External Authorization Server
Backend accessible via REST calls
For now I am using Authorization Code Grant flow.
What have I tried:
I've checked official site. There is a list of possible flows (Authorization Code, Implicit, Password, Client Credentials, Device Code, ...),
but no clear indication how to choose between them.
Then I found this excellent article on Auth0.com. Unfortunately PWA + server side beckend is not present in their scheme.
Could you please tell me what OAuth2 flow is appropriate to my context and why?
Assumptions (the way I understood the question):
You own and develop both frontend (Angular app) and backend (server-side REST API).
You want to outsource authentication to a 3rd party identity provider.
You want the Angular app (Client) to hold the token and be able to authenticate on the backend (Resource Server), with the identity of your user (Resource Owner) established on the 3rd party (Authorisation Server / Identity Provider (IdP) ).
First, a sidetrack. For this use-case, OpenId Connect (OIDC) would be a better fit, because that supports the identity element. The point in OAuth2 is to authorize your app to do stuff on the 3rd party. What you want is establish the identity of your user, with the help of the 3rd party, and that's what OpenId Connect does.
Ok, so which flow (OIDC is still based on OAuth2).
The first questions are whether the Client is trusted to do anything on the Resource Server, and whether it can securely store a secret. This is clearly not the case, a client-side app is not trusted, and cannot hold a secret. In the client credentials flow, the client uses a secret to authenticate on the IdP to receive a token for the resource server. This would mean your Angular app stores a password which it uses to get a token for your backend, clearly not what you want.
Resource owner password credentials flow is used when the client is trusted to handle user credentials. In your use-case this is not good, because practically it would mean your Angular app would get the users password to forward it to the IdP in exchange for a token. Your Client should not have access to the user password, it is not trusted.
Now comes the more interesting part.
The question is whether your Client has a server-side to securely hold a secret. If it does, Authorization Code Grant is good, because it allows your user to authenticate on the IdP, get redirected back with an authorization code, and the server-side can then exchange that for an access token to be used on the resource server. However, your Client in this scenario does not have a server-side, as far as I can understand the API is the resource server. So this is not good for you, because it needs a client secret, and you can't store it in your Angular app.
And this pretty much leaves you with the Implicit Flow, for which you don't need a client secret, but on the other hand it's difficult to do things like refresh tokens. In the flowchart you linked to, the last question is whether your Client is an SPA - and in your case it is, so you should go for the implicit flow by default.
This is probably the most secure model for you, because even in case of a compromise of your Client, your user credentials are still safe (the Angular app never has access).
However, you can model this whole thing differently, and that simplifies it quite a bit.
As far as I could understand, you own both the Client and the Resource Server, and the Resource Owner is using the Client, you just want to offload authentication while you still manage users in a 3rd party service.
Looking at it this way, your Client is trusted to access user credentials, and the user using it is the Resource Owner. So you could use the Resource Owner Password Flow, where the user enters his credentials directly into the Angular app, which goes to the IdP, gets a token, and Angular simply uses that to access stuff on the API (Resource Server).
The risk compared to the Implicit Flow is that if the Angular app is compromised, user credentials will be disclosed to the attacker. Whether you want to accept this risk entirely depends on you. Note that this would obviously not work if the IdP is a well-known service (like a social website for example), because as your user I wouldn't want to give my social site password to your app. But as long as you manage users anyway, it can be acceptable to trust the Client.
While the previous anwser was perfectly accepted in 2018, it should be considerate as a security risk nowaday.
IETF source concerning implicit flow.
The correct flow to used now for a PWA and in general any public, browser based client that can not rely on client_secret is the authorization code flow + PKCE

Is it really safe to authenticate JWT token from React frontend?

I am from a traditional HTML, frontend JS, css background so I am a little suspicious of doing token authentication from the frontend.
So when user logs in, JWT will be generated from the backend and be sent to the client. From then on, I would store it in localStorage or sessionStorage to authenticate them 'at frontend' every time user attempts to access private routes. Coming from the traditional 'always client to server communication' I am wondering if this approach is very secure. (although I do know that the decoding of JWT is exactly the same process whether it happens in the backend or the frontend). So are there any additional security breach I should be considering when routing on the frontend as opposed to routing on the backend?
EDIT**
Also, would my secret not be exposed to everyone if I decode on the frontend?
This approach is secure, and secret won't be exposed to everyone. Back end application usually reads the main uid and the access_token.
It is critical to use TLS/SSL in conjunction with JWT, to prevent man-in-the-middle attacks. In most cases, this will be sufficient to encrypt the JWT payload if it contains sensitive information. However, if we want to add an additional layer of protection, we can encrypt the JWT payload itself using the JSON Web Encryption (JWE) specification.
Of course, if we want to avoid the additional overhead of using JWE, another option is to simply keep sensitive information in our database, and use our token for additional API calls to the server whenever we need to access sensitive data.

Are OAuth Access Tokens confidential?

I have a web application which uses OAuth 2.0 to talk to a third-party service. I want both my server and my web app to talk to the authorized service on behalf of the user. I go through the normal authorization steps of doing the redirect, getting the auth code, exchanging it for the access token, all that jazz. Once complete, my server has the access token and can talk to the service. However, I'd like the web app to talk to the service as well so I don't have to route everything through my server.
Can I send the access token to the web app so I can achieve this? Or, is the access token supposed to be kept confidential between my service and the service, never being disclosed to the user, just just like the client secret is?
I've tried to find an answer for this in the spec and various blog posts, but haven't found a definitive answer either way. I know there is an implied auth method for client-side apps which don't involve a server-side component at all. Therefor my initial guess is that I can send the token to the client. I would like to verify this though.
The token is considered very sensitive information because it allows access to the service. Anyone could issue requests if they had this token.
This is why the token is passed in the Authorization Header, this is why it's highly recommended you make all calls over https, to protect the headers and body information. This is also why it is recommended that the tokens have s short life span so that if one is indeed compromised, it doesn't last for long.
Yes, you can share this token between your own applications and it should work, provided the receiver of the token does not store the IP addresses of the callers as well or has some other check mechanisms in place.
The ideal situation however would be for you to issue a different set of ClientID and Client Secret to each application which requires access.
Don't forget that this is the way the applications identify themselves to the receiver side and it might be important for reporting and analysis purposes.

Does an OAuth 2 client really need TLS?

I intend to build a delegated login system for an existing app. I'll be implementing both the OAuth client (in a web application) and the OAuth server (a simple authorization and resource server, that really only has a 'user' resource for now.)
With that in mind, I came across the following section in the current OAuth 2 draft (version 22):
3.1.2.1. Endpoint Request Confidentiality
If a redirection request will result in the transmission of an
authorization code or access token over an open network (between the
resource owner's user-agent and the client), the client SHOULD
require the use of a transport-layer security mechanism.
Lack of transport-layer security can have a severe impact on the
security of the client and the protected resources it is authorized
to access. The use of transport-layer security is particularly
critical when the authorization process is used as a form of
delegated end-user authentication by the client (e.g. third-party
sign-in service).
This specifically warns me that I should be using TLS on the client. We will be using HTTPS on the server, of course, but enabling HTTPS on all clients will be difficult if not impossible.
From my limited understanding of security, I imagine someone could steal the authorization grant. This brings me to my question:
Won't client authentication (using the client secret) prevent an eavesdropper from using the authorization grant? (Because the malicious party won't know the client secret, hopefully.)
If it doesn't, or if there's another attack vector here I'm not seeing, is there anything I can do to make this work securely without HTTPS on the clients? Would, for example, OAuth 1 help? (Perhaps because it has the additional request token step.)
P.S.: I was planning on doing client authentication using TLS client certificates, rather than secrets, if that makes the situation any better.
I think you are misinterpreting part of this warning. This OAuth warning is addressing OWASP A9 violations. This is saying that even though you are using OAuth you still need a secure transport layer to communicate with the client. The client doesn't require a key pair for authentication, OAuth is the client's form of authentication. However, the browser still authenticates with your application using a session id stored as a cookie value. The concern is that if an attacker is able to intercept this value, then he will have the same access as the victimized client.

Resources