Merge pull request #1802 from umbraco/feature/validate-token-on-first-load
Feature: Validate the token on first load
This commit is contained in:
@@ -7,6 +7,7 @@ import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export class UmbAppAuthController extends UmbControllerBase {
|
||||
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
|
||||
#isFirstCheck = true;
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host);
|
||||
@@ -37,7 +38,18 @@ export class UmbAppAuthController extends UmbControllerBase {
|
||||
const isAuthorized = this.#authContext.getIsAuthorized();
|
||||
|
||||
if (isAuthorized) {
|
||||
return true;
|
||||
// If this is the first time we are checking the authorization state (i.e. on first load), we need to make sure
|
||||
// that the token is still valid. If it is not, we need to start the authorization flow.
|
||||
// If the token is still valid, we can return true.
|
||||
if (this.#isFirstCheck) {
|
||||
this.#isFirstCheck = false;
|
||||
const isValid = await this.#authContext.validateToken();
|
||||
if (isValid) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a request to the auth server to start the auth flow
|
||||
|
||||
@@ -307,29 +307,17 @@ export class UmbAuthFlow {
|
||||
return Promise.resolve(this.#tokenResponse.accessToken);
|
||||
}
|
||||
|
||||
// if the refresh token is not set (maybe the provider doesn't support them)
|
||||
if (!this.#tokenResponse?.refreshToken) {
|
||||
this.#timeoutSignal.next();
|
||||
return Promise.reject('Missing refreshToken.');
|
||||
}
|
||||
const success = await this.makeRefreshTokenRequest();
|
||||
|
||||
const request = new TokenRequest({
|
||||
client_id: this.#clientId,
|
||||
redirect_uri: this.#redirectUri,
|
||||
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
||||
code: undefined,
|
||||
refresh_token: this.#tokenResponse.refreshToken,
|
||||
extras: undefined,
|
||||
});
|
||||
|
||||
await this.#performTokenRequest(request);
|
||||
|
||||
if (!this.#tokenResponse) {
|
||||
if (!success) {
|
||||
this.clearTokenStorage();
|
||||
this.#timeoutSignal.next();
|
||||
return Promise.reject('Missing tokenResponse.');
|
||||
}
|
||||
|
||||
return Promise.resolve(this.#tokenResponse.accessToken);
|
||||
return this.#tokenResponse
|
||||
? Promise.resolve(this.#tokenResponse.accessToken)
|
||||
: Promise.reject('Missing tokenResponse.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,18 +352,36 @@ export class UmbAuthFlow {
|
||||
await this.#performTokenRequest(request);
|
||||
}
|
||||
|
||||
async makeRefreshTokenRequest(): Promise<boolean> {
|
||||
if (!this.#tokenResponse?.refreshToken) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const request = new TokenRequest({
|
||||
client_id: this.#clientId,
|
||||
redirect_uri: this.#redirectUri,
|
||||
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
||||
code: undefined,
|
||||
refresh_token: this.#tokenResponse.refreshToken,
|
||||
extras: undefined,
|
||||
});
|
||||
|
||||
return this.#performTokenRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will make a token request to the server using the refresh token.
|
||||
* If the request fails, it will sign the user out (clear the token state).
|
||||
*/
|
||||
async #performTokenRequest(request: TokenRequest): Promise<void> {
|
||||
async #performTokenRequest(request: TokenRequest): Promise<boolean> {
|
||||
try {
|
||||
this.#tokenResponse = await this.#tokenHandler.performTokenRequest(this.#configuration, request);
|
||||
this.#saveTokenState();
|
||||
return true;
|
||||
} catch (error) {
|
||||
// If the token request fails, it means the code or refresh token is invalid
|
||||
this.clearTokenStorage();
|
||||
console.error('Token request error', error);
|
||||
this.clearTokenStorage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,15 @@ export class UmbAuthContext extends UmbContextBase<UmbAuthContext> {
|
||||
return this.#authFlow.performWithFreshTokens();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the token against the server and returns true if the token is valid.
|
||||
* @memberof UmbAuthContext
|
||||
* @returns True if the token is valid, otherwise false
|
||||
*/
|
||||
async validateToken(): Promise<boolean> {
|
||||
return this.#authFlow.makeRefreshTokenRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the token storage.
|
||||
* @memberof UmbAuthContext
|
||||
@@ -188,7 +197,6 @@ export class UmbAuthContext extends UmbContextBase<UmbAuthContext> {
|
||||
* @memberof UmbAuthContext
|
||||
*/
|
||||
timeOut() {
|
||||
this.clearTokenStorage();
|
||||
this.#isAuthorized.setValue(false);
|
||||
this.#isTimeout.next();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user