Skip to content

Commit dc61724

Browse files
committed
fix(login): fix "retry online login" action
and handle login problems more smoothly fixes #2420
1 parent 109b023 commit dc61724

File tree

3 files changed

+50
-22
lines changed

3 files changed

+50
-22
lines changed

src/app/core/session/auth/keycloak/keycloak-auth.service.ts

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { LoggingService } from "../../../logging/logging.service";
88
import { Entity } from "../../../entity/model/entity";
99
import { User } from "../../../user/user";
1010
import { ParsedJWT, parseJwt } from "../../../../session/session-utils";
11+
import { RemoteLoginNotAvailableError } from "./remote-login-not-available.error";
1112

1213
/**
1314
* Handles the remote session with keycloak
@@ -33,8 +34,23 @@ export class KeycloakAuthService {
3334
*/
3435
async login(): Promise<SessionInfo> {
3536
if (!this.keycloakInitialised) {
36-
this.keycloakInitialised = true;
37-
const loggedIn = await this.keycloak.init({
37+
await this.initKeycloak();
38+
}
39+
40+
await this.keycloak.updateToken();
41+
let token = await this.keycloak.getToken();
42+
if (!token) {
43+
// Forward to the keycloak login page.
44+
await this.keycloak.login({ redirectUri: location.href });
45+
token = await this.keycloak.getToken();
46+
}
47+
48+
return this.processToken(token);
49+
}
50+
51+
private async initKeycloak() {
52+
try {
53+
await this.keycloak.init({
3854
config: window.location.origin + "/assets/keycloak.json",
3955
initOptions: {
4056
onLoad: "check-sso",
@@ -44,28 +60,31 @@ export class KeycloakAuthService {
4460
// GitHub API rejects if non GitHub bearer token is present
4561
shouldAddToken: ({ url }) => !url.includes("api.github.com"),
4662
});
47-
if (!loggedIn) {
48-
// Forward to the keycloak login page.
49-
await this.keycloak.login({ redirectUri: location.href });
63+
} catch (err) {
64+
if (
65+
err?.error ===
66+
"Timeout when waiting for 3rd party check iframe message."
67+
) {
68+
// this is actually an expected scenario, user's internet is slow or not available
69+
err = new RemoteLoginNotAvailableError();
70+
} else {
71+
this.logger.error("Keycloak init failed", err);
5072
}
5173

52-
// auto-refresh expiring tokens, as suggested by https://github.com/mauriciovigolo/keycloak-angular?tab=readme-ov-file#keycloak-js-events
53-
this.keycloak.keycloakEvents$.subscribe((event) => {
54-
if (event.type == KeycloakEventType.OnTokenExpired) {
55-
this.login().catch((err) =>
56-
this.logger.debug("automatic token refresh failed", err),
57-
);
58-
}
59-
});
74+
this.keycloakInitialised = false;
75+
throw err;
6076
}
6177

62-
return this.keycloak
63-
.updateToken()
64-
.then(() => {
65-
return this.keycloak.getToken();
66-
// TODO: should we notify the user to manually log in again when failing to refresh token?
67-
})
68-
.then((token) => this.processToken(token));
78+
// auto-refresh expiring tokens, as suggested by https://github.com/mauriciovigolo/keycloak-angular?tab=readme-ov-file#keycloak-js-events
79+
this.keycloak.keycloakEvents$.subscribe((event) => {
80+
if (event.type == KeycloakEventType.OnTokenExpired) {
81+
this.login().catch((err) =>
82+
this.logger.debug("automatic token refresh failed", err),
83+
);
84+
}
85+
});
86+
87+
this.keycloakInitialised = true;
6988
}
7089

7190
private processToken(token: string): SessionInfo {
@@ -119,7 +138,7 @@ export class KeycloakAuthService {
119138
* Forward to the keycloak logout endpoint to clear the session.
120139
*/
121140
async logout() {
122-
return this.keycloak.logout(location.href);
141+
return await this.keycloak.logout(location.href);
123142
}
124143

125144
/**
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Custom error indicating that Remote Auth Server cannot be reached.
3+
*/
4+
export class RemoteLoginNotAvailableError extends Error {
5+
constructor() {
6+
super("Remote login currently unavailable.");
7+
Object.setPrototypeOf(this, RemoteLoginNotAvailableError.prototype);
8+
}
9+
}

src/app/core/session/session-service/session-manager.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class SessionManagerService {
8080
.then((user) => this.handleRemoteLogin(user))
8181
.catch((err) => {
8282
this.loginStateSubject.next(LoginState.LOGIN_FAILED);
83-
throw err;
83+
// ignore fall back to offline login - if there was a technical error, the AuthService has already logged/reported it
8484
});
8585
}
8686
this.loginStateSubject.next(LoginState.LOGIN_FAILED);

0 commit comments

Comments
 (0)