Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
feat(authService): add default headers and clientSecret in config
Browse files Browse the repository at this point in the history
Add some default headers to the baseConfig that will be appended when using .login() and .refreshToken(). This is to support IdentityServer 4 with the openId spec http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest.
Gives us the posibility to use application/x-www-form-urlencoded as content-type.
  • Loading branch information
Mats Grønlid committed Feb 2, 2017
1 parent c119d0c commit 863e4a4
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
6 changes: 6 additions & 0 deletions doc/baseConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ useRefreshToken = false;
autoUpdateToken = true;
// Oauth Client Id
clientId = false;
// Oauth Client secret
clientSecret = null;
// The property from which to get the refresh token after a successful token refresh
refreshTokenProp = 'refresh_token';

Expand Down Expand Up @@ -138,6 +140,10 @@ getRefreshTokenFromResponse = null;
// List of value-converters to make global
globalValueConverters = ['authFilterValueConverter'];

// Default headers for login and token-update endpoint
defaultHeadersForTokenRequests = {
'Content-Type': 'application/json'
}

//OAuth provider specific related configuration
// ============================================
Expand Down
20 changes: 15 additions & 5 deletions src/authService.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,21 @@ export class AuthService {

if (this.authentication.updateTokenCallstack.length === 0) {
let content = {
grant_type: 'refresh_token',
client_id : this.config.clientId ? this.config.clientId : undefined
grant_type: 'refresh_token'
};

if(this.config.clientId) {
content.client_id = this.config.clientId;
}
if(this.config.clientSecret) {
content.client_secret = this.config.clientSecret;
}

content[this.config.refreshTokenSubmitProp] = this.authentication.getRefreshToken();

this.client.post(this.config.joinBase(this.config.refreshTokenUrl
? this.config.refreshTokenUrl
: this.config.loginUrl), content)
: this.config.loginUrl), content, this.config.getOptionsForTokenRequests())
.then(response => {
this.setResponseObject(response);
this.authentication.resolveUpdateTokenCallstack(this.isAuthenticated());
Expand Down Expand Up @@ -442,21 +448,25 @@ export class AuthService {

if (typeof emailOrCredentials === 'object') {
normalized.credentials = emailOrCredentials;
normalized.options = passwordOrOptions;
normalized.options = this.config.getOptionsForTokenRequests(passwordOrOptions);
normalized.redirectUri = optionsOrRedirectUri;
} else {
normalized.credentials = {
'email' : emailOrCredentials,
'password': passwordOrOptions
};
normalized.options = optionsOrRedirectUri;
normalized.options = this.config.getOptionsForTokenRequests(optionsOrRedirectUri);
normalized.redirectUri = redirectUri;
}

if (this.config.clientId) {
normalized.credentials.client_id = this.config.clientId;
}

if(this.config.clientSecret) {
normalized.credentials.client_secret = this.config.clientSecret;
}

return this.client.post(this.config.joinBase(this.config.loginUrl), normalized.credentials, normalized.options)
.then(response => {
this.setResponseObject(response);
Expand Down
11 changes: 11 additions & 0 deletions src/baseConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export class BaseConfig {
}
}

getOptionsForTokenRequests(options?:{} = {}): {} {
return extend(true, {}, {headers: this.defaultHeadersForTokenRequests}, options);
}

/* ----------- default config ----------- */

// Used internally. The used Rest instance; set during configuration (see index.js)
Expand Down Expand Up @@ -117,6 +121,8 @@ export class BaseConfig {
autoUpdateToken = true;
// Oauth Client Id
clientId = false;
// Oauth Client secret
clientSecret = null;
// The the property from which to get the refresh token after a successful token refresh. Can also be dotted eg "refreshTokenProp.refreshTokenProp"
refreshTokenProp = 'refresh_token';
// The property name used to send the existing token when refreshing `{ "refreshTokenSubmitProp": '...' }`
Expand Down Expand Up @@ -166,6 +172,11 @@ export class BaseConfig {
// List of value-converters to make global
globalValueConverters = ['authFilterValueConverter'];

// Default headers for login and token-update endpoint
defaultHeadersForTokenRequests = {
'Content-Type': 'application/json'
}

//OAuth provider specific related configuration
// ============================================
providers = {
Expand Down
23 changes: 23 additions & 0 deletions test/baseConfig.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,27 @@ describe('BaseConfig', () => {
expect(baseConfig.joinBase('/xy')).toBe('http://localhost:1927/xy');
});
});

describe('.getOptionsForTokenRequests()', () => {
it('When given empty or undefined object as input, should return default values set in config object', () => {
const container = new Container();
const baseConfig = container.get(BaseConfig);
const resultOptions = baseConfig.getOptionsForTokenRequests();

expect(resultOptions.headers['Content-Type']).toBe(baseConfig.defaultHeadersForTokenRequests['Content-Type']);
});

it('When given object with values, should return object with values overridden by input object', () => {
const container = new Container();
const baseConfig = container.get(BaseConfig);
const contentType = 'test';
const resultOptions = baseConfig.getOptionsForTokenRequests({
headers: {
'Content-Type': contentType
}
});

expect(resultOptions.headers['Content-Type']).toBe(resultOptions.headers['Content-Type']);
});
});
});

3 comments on commit 863e4a4

@pllamena
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,

I am running into an issue with the defaultHeadersForTokenRequests.

It seems to be working for the login() method, but not for updateToken(). All the parameters are missing from the updateToken request, which also happens for the initial token request made by login() if I remove the defaultHeadersForTokenRequests: {'Content-Type': 'application/x-www-form-urlencoded'} line.

Here is my set up:

.plugin('aurelia-api', configure => {
configure.registerEndpoint('auth', environment.apiEndpoint, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
.registerEndpoint('protected-api', environment.apiEndpoint)
.setDefaultEndpoint('protected-api')
})
.plugin('aurelia-authentication', baseConfig => {
baseConfig.configure({
endpoint: 'auth',
configureEndpoints: ['auth','protected-api'],
defaultHeadersForTokenRequests: {'Content-Type': 'application/x-www-form-urlencoded'},
loginUrl: 'token',
authHeader: 'Authorization',
authTokenType: 'Bearer',
httpInterceptor: true,
accessTokenProp: 'access_token',
useRefreshToken: true,
clientId: 'XXXXXXXX',
refreshTokenUrl: 'token',
refreshTokenProp: 'refresh_token',
refreshTokenSubmitProp: 'refresh_token',
autoUpdateToken: true,
storage: 'localStorage',
loginRedirect: '#/home',
logoutRedirect: '#/home',
getExpirationDateFromResponse: (response => { if(response && response.expires_in) return (new Date().getTime() + response.expires_in * 1000)/1000})
})
})

Am I missing something? Please let me know if more details are needed!

Thank you!

@RWOverdijk
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pllamena could you move this to an issue, and ping @groenlid?

@pllamena
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I just created issue #358 :)

Please sign in to comment.