I would like to use OAuth to authorize users (identified by username, password) on an intranet, but I don't quite understand how to use OAuth to fulfill my needs.
My main concern is to prevent the backend (Client), to collect the user's passwords and the frontend, to receive the access-token.
If I use the Password Grant Type, only the frontend could collect the users credentials, however as there is no redirection nor authorization code for this Grant scheme, the frontend will also get the access token which can therefore be stolen.
Also, with this Password Grant Type, the frontend have to provide both the client_id and client_password which is only known by the backend.
How can use OAuth with Password Grant in this situation?
The use-case
I am writing an intranet platform that should accept users from an Active Directory server. The naive solution is to use a form such as:
<form method="post">
<input type="text" name="username" required>
<input type="password" name="password" required>
<input type="submit" name="login">
</form>
Therefore the backend can verify the received credentials with the Active Directory server. But, this is a very insecure solution because the backend could collect the user's passwords. As I am writing the application, this is very tempting :(
So, I would like to setup third-party OAuth server out of my control in order to use this form instead:
<form action="http://oauth.company.com" method="post">
<input type="hidden" name="redirect" value="http://intranet.company.com">
<input type="hidden" name="grant_type" value="password">
<input type="hidden" name="client_id" value="badbeef">
<input type="text" name="username" required>
<input type="password" name="password" required>
<input type="submit" name="login">
</form>
With this solution, only the frontend will see the password, but as any user could check the source code, this prevents me to try to grab their passwords because I would be too much exposed.
With the OAuth Password Grant scheme, I have two problems:
- The frontend must be aware of the
client_secret. - The frontend will receive the access token.
So I would like either solutions:
- The frontend get an authorization-code that will be then transmitted to the backend
- The Authorization Server personally informs the backend of the access token.
The wished authentication flow
From the Frontend, the Resource Owner enters his credentials that are sent to the Authorization Server, thus the Client does not know the Resource Owner credentials.
POST /oauth/token HTTP/1.1
Host: oauth.company.com
grant_type=password
&username=jdoe
&password=secret
&client_id=intranet-id
&state=123
&redirect=http://intranet.company.com/auth
The Authorization Server grant the user and sends this back to the fontend:
HTTP/1.1 302 Found
Location: https://intranet.company.com/auth?code=g0ZGZmNjVmOWI&state=dkZmYxMzE2
Then the backend requests the access-token with the received code:
POST /oauth/token HTTP/1.1
Host: oauth.company.com
grant_type=????
&code=g0ZGZmNjVmOWI&state=dkZmYxMzE2
&client_id=intranet-id
&client_secret=intranet-secret
Then it receives:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create"
}
From this point, the backend redirects the frontend to the intranet portal.