Last active
August 18, 2023 17:50
-
-
Save zerkalica/911562364a870d0515c3bdea10a25c8d to your computer and use it in GitHub Desktop.
keycloak
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace $ { | |
export class $gd_rad_session_web extends $gd_rad_session { | |
client_id() { | |
return 'pa-admin' | |
} | |
@ $mol_mem | |
token_access(next?: string | null) { | |
return this.$.$gd_rad_transport.token(next) ?? undefined | |
} | |
@ $mol_mem | |
token_refresh(next?: string | null) { | |
return this.$.$mol_state_local.value('kc_mol_rt', next) ?? undefined | |
} | |
@ $mol_mem | |
token_idt(next?: string | null) { | |
return this.$.$mol_state_local.value('kc_mol_idt', next) ?? undefined | |
} | |
minValidity() { | |
return 30 | |
} | |
@ $mol_mem | |
// https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter | |
protected kc_raw() { | |
const oidc = this.oidc() | |
const clientId = this.client_id() | |
if (!oidc?.realm || !clientId) throw new Error('No oidc.realm: setup application') | |
const kc = new $lib_keycloak({ | |
url: oidc.url, | |
realm: oidc.realm, | |
clientId, | |
}) | |
kc.onAuthRefreshSuccess = $mol_wire_async(() => this.success()) | |
kc.onAuthRefreshError = $mol_wire_async(() => this.error()) | |
kc.onTokenExpired = $mol_wire_async(() => this.update()) | |
// kc.destructor = () => kc.clearToken() | |
return $mol_wire_sync(kc as typeof kc & { didInitialize?: boolean }) | |
} | |
// При возврате с сайта авторизации, keycloak пихает свои параметры в урл. | |
// вызов kc.init выпиливает их, т.е. меняет href, который аргумент у kc.init | |
// Поэтому mol запускает kc.init с нуля и тот падает, т.к. проверяет повторные запуски | |
// mol_action кэшит href до завершения kc_inited и аргументы kc.init не меняются | |
@ $mol_action | |
protected href() { | |
return this.$.$mol_dom_context.location.href | |
} | |
// Задача получить настроенный инстанс keycloak | |
// Сам инстанс создается в kc_raw и кэшируется, однако у инстанса надо еще вызвать асинхронный метод kc.init | |
// Хелпер $mol_wire_sync делает этот метод псевдосинхронным | |
// Т.к. init надо вызовать только один раз, то реактивную связь с token_access и пр. параметрами надо разорвать | |
// Для этого и нужна связка mol_mem + mol_action | |
// экшен не дает подписываться на метод из которого вызван, а mem кэшит результат экшена | |
@ $mol_mem | |
@ $mol_action | |
kc() { | |
const kc = this.kc_raw() | |
kc.init({ | |
token: this.token_access(), | |
idToken: this.token_idt(), | |
refreshToken: this.token_refresh(), | |
redirectUri: this.href(), | |
timeSkew: 0, | |
}) | |
if (kc.authenticated && this.expired()) this.update() | |
this.success() | |
return kc | |
} | |
@ $mol_action | |
override update(validity = this.minValidity()) { | |
return this.kc_raw().updateToken(validity) | |
} | |
expired() { | |
return this.kc_raw().isTokenExpired(this.minValidity()) | |
} | |
@ $mol_action | |
success() { | |
const kc = this.kc_raw() | |
this.token_access(kc.token) | |
this.token_refresh(kc.refreshToken) | |
this.token_idt(kc.idToken) | |
} | |
@ $mol_action | |
clear() { | |
const place = '$gd_rad_session:clear' | |
this.$.$mol_log3_come({ message: 'begin update token', place }) | |
const refreshed = this.update(-1) | |
this.$.$mol_log3_done({ message: 'done update token, refreshed=' + refreshed, place }) | |
} | |
@ $mol_action | |
error() { | |
this.token_access(null) | |
this.token_refresh(null) | |
this.token_idt(null) | |
} | |
register_url() { | |
return this.kc().createRegisterUrl({ | |
redirectUri: $mol_dom_context.location.href | |
}) | |
} | |
login_url() { | |
return this.kc().createLoginUrl({ | |
redirectUri: $mol_dom_context.location.href | |
}) | |
} | |
override login_start() { | |
this.$.$mol_dom_context.location.replace(this.login_url()) | |
} | |
override register() { | |
this.$.$mol_dom_context.location.replace(this.register_url()) | |
} | |
override token() { | |
this.kc() | |
return this.token_access() | |
} | |
} | |
$.$gd_rad_session = $gd_rad_session_web | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment