Skip to content

Commit

Permalink
fix(auth): fix OAuth2 strategy grant_type password to send username, …
Browse files Browse the repository at this point in the history
…not email (#659)

BREAKING CHANGE:
According to RFC6749 section 4.3.2, the OAuth2 token request body with grant-type='password' must provide `username` to the auth server and not `email`.
Closes #653
  • Loading branch information
alain-charles authored and nnixaa committed Aug 23, 2018
1 parent 73cf1b4 commit 3a708dd
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ app.post('/api/auth/login', function (req, res) {

app.post('/api/auth/token', function (req, res) {

if (req.body.email && req.body.password) {
var email = req.body.email;
if (req.body.username && req.body.password) {
var email = req.body.username;
var password = req.body.password;
var user = users.find(function (u) {
return u.email === email && u.password === password;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class NbOAuth2AuthStrategyOptions extends NbAuthStrategyOptions {
endpoint?: string;
grantType?: string;
redirectUri?: string;
scope?: string; // Used only with 'password' grantType
requireValidToken?: boolean;
class: NbAuthTokenClass,
} = {
Expand Down
18 changes: 12 additions & 6 deletions src/framework/auth/strategies/oauth2/oauth2-strategy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -654,13 +654,15 @@ describe('oauth2-auth-strategy', () => {

describe('configured: additionnal param: token, grant_type:password', () => {

const scope = 'theScope';
const basicOptions = {
name: 'strategy',
baseEndpoint: 'http://example.com/',
clientId: 'clientId',
token: {
grantType: NbOAuth2GrantType.PASSWORD,
endpoint: 'token',
scope: scope,
},
}

Expand All @@ -687,8 +689,9 @@ describe('oauth2-auth-strategy', () => {
httpMock.expectOne(
req => req.url === 'http://example.com/token'
&& req.body['grant_type'] === NbOAuth2GrantType.PASSWORD
&& req.body['email'] === credentials.email
&& req.body['password'] === credentials.password,
&& req.body['username'] === credentials.email
&& req.body['password'] === credentials.password
&& req.body['scope'] === scope,
).flush(tokenSuccessResponse);
});

Expand Down Expand Up @@ -717,7 +720,8 @@ describe('oauth2-auth-strategy', () => {
req => req.url === 'http://example.com/token'
&& req.headers.get('Authorization') === authHeader
&& req.body['grant_type'] === NbOAuth2GrantType.PASSWORD
&& req.body['email'] === credentials.email
&& req.body['username'] === credentials.email
&& req.body['scope'] === scope
&& req.body['password'] === credentials.password,
).flush(tokenSuccessResponse);
});
Expand Down Expand Up @@ -746,8 +750,9 @@ describe('oauth2-auth-strategy', () => {
httpMock.expectOne(
req => req.url === 'http://example.com/token'
&& req.body['grant_type'] === NbOAuth2GrantType.PASSWORD
&& req.body['email'] === credentials.email
&& req.body['username'] === credentials.email
&& req.body['password'] === credentials.password
&& req.body['scope'] === scope
&& req.body['client_id'] === strategy.getOption('clientId')
&& req.body['client_secret'] === strategy.getOption('clientSecret'),
).flush(tokenSuccessResponse);
Expand All @@ -773,8 +778,9 @@ describe('oauth2-auth-strategy', () => {
httpMock.expectOne(
req => req.url === 'http://example.com/token'
&& req.body['grant_type'] === NbOAuth2GrantType.PASSWORD
&& req.body['email'] === credentials.email
&& req.body['password'] === credentials.password,
&& req.body['username'] === credentials.email
&& req.body['password'] === credentials.password
&& req.body['scope'] === scope,
).flush(tokenErrorResponse, {status: 401, statusText: 'unauthorized'});
});
});
Expand Down
10 changes: 6 additions & 4 deletions src/framework/auth/strategies/oauth2/oauth2-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import { NbAuthStrategyClass } from '../../auth.options';
* grantType?: string;
* requireValidToken: false,
* redirectUri?: string;
* scope?: string;
* class: NbAuthTokenClass,
* } = {
* endpoint: 'token',
Expand Down Expand Up @@ -237,12 +238,12 @@ export class NbOAuth2AuthStrategy extends NbAuthStrategy {
);
}

passwordToken(email: string, password: string): Observable<NbAuthResult> {
passwordToken(username: string, password: string): Observable<NbAuthResult> {
const module = 'token';
const url = this.getActionEndpoint(module);
const requireValidToken = this.getOption(`${module}.requireValidToken`);

return this.http.post(url, this.buildPasswordRequestData(email, password), this.buildAuthHeader() )
return this.http.post(url, this.buildPasswordRequestData(username, password), this.buildAuthHeader() )
.pipe(
map((res) => {
return new NbAuthResult(
Expand Down Expand Up @@ -306,11 +307,12 @@ export class NbOAuth2AuthStrategy extends NbAuthStrategy {
return this.cleanParams(this.addCredentialsToParams(params));
}

protected buildPasswordRequestData(email: string, password: string ): any {
protected buildPasswordRequestData(username: string, password: string ): any {
const params = {
grant_type: this.getOption('token.grantType'),
email: email,
username: username,
password: password,
scope: this.getOption('token.scope'),
};
return this.cleanParams(this.addCredentialsToParams(params));
}
Expand Down

0 comments on commit 3a708dd

Please sign in to comment.