I’m creating a new application with a set of microservices and frontend using React. I have my own auth server using Oauth. Ideally I want to keep the user login and register process within the React app as I own both the auth server and the client application.
I wanted to use the password grant but due to React being a single page application, I can’t protect the secret. I can use the implicit grant but don’t really want to redirect the user away to another page to login or register. This would be ok for future third party integration but as I own the frontend, I wish to make it seamless as possible (e.g. like Facebook).
As an alternative, could I create a user microservice (where I can protect the secret) which provides API’s for login and register which then call the auth service using the password grant?
4
Answers
I believe what you want to have is "Resource Owner Password Credentials Grant". In this Oauth 2 flow, end user (the resource owner) provide client their credentials, trusting the client. Client use these credentials to exchange token from Authorization server. Your front end should not store credentials. But as always, it will require to store tokens.
Once the front end obtain tokens, then it can communicate with servers you have. And they must be protected by tokens, which you validate against authorisation server.
I guess by secret you meant client secret?
Since React is javascript, you can not protect client secret and you do not want to use implicit grant, having a service/micro service as UI back end is a good approach. UI backend can secure client secret and create tokens using your OAuth server. Then UI front end will invoke UI backend API. UI backend can use
password
grant type to create tokens at user login.You have two problems here.
One is how to authenticate the SPA without leaking the client_ secret and the other how to you securely store the access token in the frontend once you have solved the first problem.
I would recommend this approach
Create a backend proxy running on the same domain name as your SPA – this can still be your authentication backend.
You can then post credentials from your SPA to this proxy backend to have your user authenticated using password grant.
After authentication you can return the access_token (or normal session based authentication) to the client through a secure http cookie which will make your SPA API requests authenticated via the cookie.
That will have introduced another problem that you need to take care of. CSRF – You can generate a CSRF token, send it to the client through a normal
XSRF-TOKEN
cookie which will be automatically picked by your http client like axies and returned to the server throughX-XSRF-TOKEN
header.Once the csrf token is received in the proxy you can compare with the one on the cookie or the one in your session before allowing the request to continue.
Other things to look at will be securing CORS headers and ensuring only requests from your SPA domain name are accepted by your server.
I believe this is the reason
PKCE
was created. CSRF attacks can be prevented by issuing a challenge on the fly, and without using a secret.See also rfc7636