Permalink
Browse files

feat(authService): add default headers and clientSecret in config

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
Mats Grønlid committed Feb 2, 2017
1 parent c119d0c commit 863e4a484b29775644e77b64b103424c8e63d39b
Showing with 55 additions and 5 deletions.
  1. +6 −0 doc/baseConfig.md
  2. +15 −5 src/authService.js
  3. +11 −0 src/baseConfig.js
  4. +23 −0 test/baseConfig.spec.js
@@ -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';
@@ -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
// ============================================
@@ -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());
@@ -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);
@@ -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)
@@ -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": '...' }`
@@ -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 = {
@@ -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

This comment has been minimized.

pllamena replied Jul 10, 2017

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

This comment has been minimized.

Member

RWOverdijk replied Jul 10, 2017

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

@pllamena

This comment has been minimized.

pllamena replied Jul 10, 2017

Thank you! I just created issue #358 :)

Please sign in to comment.