Persist API key creds for token refresh. (#414)
* Persist API key creds for token refresh. * Linter fixes
This commit is contained in:
parent
5e24a70a87
commit
78ae9383fb
|
@ -1,6 +1,8 @@
|
|||
export abstract class ApiKeyService {
|
||||
setInformation: (clientId: string) => Promise<any>;
|
||||
setInformation: (clientId: string, clientSecret: string) => Promise<any>;
|
||||
clear: () => Promise<any>;
|
||||
getClientId: () => Promise<string>;
|
||||
getClientSecret: () => Promise<string>;
|
||||
getEntityType: () => Promise<string>;
|
||||
getEntityId: () => Promise<string>;
|
||||
isAuthenticated: () => Promise<boolean>;
|
||||
|
|
|
@ -1312,8 +1312,8 @@ export class ApiService implements ApiServiceAbstraction {
|
|||
async getActiveBearerToken(): Promise<string> {
|
||||
let accessToken = await this.tokenService.getToken();
|
||||
if (this.tokenService.tokenNeedsRefresh()) {
|
||||
const tokenResponse = await this.doRefreshToken();
|
||||
accessToken = tokenResponse.accessToken;
|
||||
await this.doRefreshToken();
|
||||
accessToken = await this.tokenService.getToken();
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
@ -1358,6 +1358,43 @@ export class ApiService implements ApiServiceAbstraction {
|
|||
}
|
||||
}
|
||||
|
||||
protected async doRefreshToken(): Promise<void> {
|
||||
const refreshToken = await this.tokenService.getRefreshToken();
|
||||
if (refreshToken == null || refreshToken === '') {
|
||||
throw new Error();
|
||||
}
|
||||
const headers = new Headers({
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'Accept': 'application/json',
|
||||
'Device-Type': this.deviceType,
|
||||
});
|
||||
if (this.customUserAgent != null) {
|
||||
headers.set('User-Agent', this.customUserAgent);
|
||||
}
|
||||
|
||||
const decodedToken = this.tokenService.decodeToken();
|
||||
const response = await this.fetch(new Request(this.identityBaseUrl + '/connect/token', {
|
||||
body: this.qsStringify({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: decodedToken.client_id,
|
||||
refresh_token: refreshToken,
|
||||
}),
|
||||
cache: 'no-store',
|
||||
credentials: this.getCredentials(),
|
||||
headers: headers,
|
||||
method: 'POST',
|
||||
}));
|
||||
|
||||
if (response.status === 200) {
|
||||
const responseJson = await response.json();
|
||||
const tokenResponse = new IdentityTokenResponse(responseJson);
|
||||
await this.tokenService.setTokens(tokenResponse.accessToken, tokenResponse.refreshToken);
|
||||
} else {
|
||||
const error = await this.handleError(response, true, true);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async send(method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, body: any,
|
||||
authed: boolean, hasResponse: boolean, apiUrl?: string,
|
||||
alterHeaders?: (headers: Headers) => void): Promise<any> {
|
||||
|
@ -1427,44 +1464,6 @@ export class ApiService implements ApiServiceAbstraction {
|
|||
return new ErrorResponse(responseJson, response.status, tokenError);
|
||||
}
|
||||
|
||||
private async doRefreshToken(): Promise<IdentityTokenResponse> {
|
||||
const refreshToken = await this.tokenService.getRefreshToken();
|
||||
if (refreshToken == null || refreshToken === '') {
|
||||
throw new Error();
|
||||
}
|
||||
const headers = new Headers({
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'Accept': 'application/json',
|
||||
'Device-Type': this.deviceType,
|
||||
});
|
||||
if (this.customUserAgent != null) {
|
||||
headers.set('User-Agent', this.customUserAgent);
|
||||
}
|
||||
|
||||
const decodedToken = this.tokenService.decodeToken();
|
||||
const response = await this.fetch(new Request(this.identityBaseUrl + '/connect/token', {
|
||||
body: this.qsStringify({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: decodedToken.client_id,
|
||||
refresh_token: refreshToken,
|
||||
}),
|
||||
cache: 'no-store',
|
||||
credentials: this.getCredentials(),
|
||||
headers: headers,
|
||||
method: 'POST',
|
||||
}));
|
||||
|
||||
if (response.status === 200) {
|
||||
const responseJson = await response.json();
|
||||
const tokenResponse = new IdentityTokenResponse(responseJson);
|
||||
await this.tokenService.setTokens(tokenResponse.accessToken, tokenResponse.refreshToken);
|
||||
return tokenResponse;
|
||||
} else {
|
||||
const error = await this.handleError(response, true, true);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
private qsStringify(params: any): string {
|
||||
return Object.keys(params).map(key => {
|
||||
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Utils } from '../misc/utils';
|
|||
|
||||
const Keys = {
|
||||
clientId: 'clientId',
|
||||
clientSecret: 'clientSecret',
|
||||
entityType: 'entityType',
|
||||
entityId: 'entityId',
|
||||
};
|
||||
|
@ -13,13 +14,15 @@ const Keys = {
|
|||
|
||||
export class ApiKeyService implements ApiKeyServiceAbstraction {
|
||||
private clientId: string;
|
||||
private clientSecret: string;
|
||||
private entityType: string;
|
||||
private entityId: string;
|
||||
|
||||
constructor(private tokenService: TokenService, private storageService: StorageService) { }
|
||||
|
||||
async setInformation(clientId: string) {
|
||||
async setInformation(clientId: string, clientSecret: string) {
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
const idParts = clientId.split('.');
|
||||
|
||||
if (idParts.length !== 2 || !Utils.isGuid(idParts[1])) {
|
||||
|
@ -31,6 +34,21 @@ export class ApiKeyService implements ApiKeyServiceAbstraction {
|
|||
await this.storageService.save(Keys.clientId, this.clientId);
|
||||
await this.storageService.save(Keys.entityId, this.entityId);
|
||||
await this.storageService.save(Keys.entityType, this.entityType);
|
||||
await this.storageService.save(Keys.clientSecret, this.clientSecret);
|
||||
}
|
||||
|
||||
async getClientId(): Promise<string> {
|
||||
if (this.clientId == null) {
|
||||
this.clientId = await this.storageService.get<string>(Keys.clientId);
|
||||
}
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
async getClientSecret(): Promise<string> {
|
||||
if (this.clientSecret == null) {
|
||||
this.clientSecret = await this.storageService.get<string>(Keys.clientSecret);
|
||||
}
|
||||
return this.clientSecret;
|
||||
}
|
||||
|
||||
async getEntityType(): Promise<string> {
|
||||
|
@ -49,10 +67,11 @@ export class ApiKeyService implements ApiKeyServiceAbstraction {
|
|||
|
||||
async clear(): Promise<any> {
|
||||
await this.storageService.remove(Keys.clientId);
|
||||
await this.storageService.remove(Keys.clientSecret);
|
||||
await this.storageService.remove(Keys.entityId);
|
||||
await this.storageService.remove(Keys.entityType);
|
||||
|
||||
this.clientId = this.entityId = this.entityType = null;
|
||||
this.clientId = this.clientSecret = this.entityId = this.entityType = null;
|
||||
}
|
||||
|
||||
async isAuthenticated(): Promise<boolean> {
|
||||
|
|
Loading…
Reference in New Issue