store user data in memory
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
c0bb1f7347
commit
f9eed9f065
23
web/package-lock.json
generated
23
web/package-lock.json
generated
|
@ -37,6 +37,7 @@
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"lit": "^2.8.0",
|
"lit": "^2.8.0",
|
||||||
"mermaid": "^10.6.1",
|
"mermaid": "^10.6.1",
|
||||||
|
"oidc-client-ts": "^2.4.0",
|
||||||
"rapidoc": "^9.3.4",
|
"rapidoc": "^9.3.4",
|
||||||
"style-mod": "^4.1.0",
|
"style-mod": "^4.1.0",
|
||||||
"webcomponent-qr-code": "^1.2.0",
|
"webcomponent-qr-code": "^1.2.0",
|
||||||
|
@ -9292,6 +9293,11 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypto-js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||||
|
},
|
||||||
"node_modules/crypto-random-string": {
|
"node_modules/crypto-random-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||||
|
@ -13226,6 +13232,11 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jwt-decode": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.3",
|
"version": "4.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
||||||
|
@ -14789,6 +14800,18 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oidc-client-ts": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-WijhkTrlXK2VvgGoakWJiBdfIsVGz6CFzgjNNqZU1hPKV2kyeEaJgLs7RwuiSp2WhLfWBQuLvr2SxVlZnk3N1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"jwt-decode": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/on-finished": {
|
"node_modules/on-finished": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ROUTES } from "@goauthentik/admin/Routes";
|
import { ROUTES } from "@goauthentik/admin/Routes";
|
||||||
import { OAuthInterface } from "@goauthentik/app/common/oauth/interface";
|
import { OAuthInterface } from "@goauthentik/app/common/oauth/interface";
|
||||||
|
import { adminSettings } from "@goauthentik/app/common/oauth/settings";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import {
|
import {
|
||||||
EVENT_API_DRAWER_TOGGLE,
|
EVENT_API_DRAWER_TOGGLE,
|
||||||
|
@ -18,6 +19,7 @@ import { getURLParam, updateURLParams } from "@goauthentik/elements/router/Route
|
||||||
import "@goauthentik/elements/router/RouterOutlet";
|
import "@goauthentik/elements/router/RouterOutlet";
|
||||||
import "@goauthentik/elements/sidebar/Sidebar";
|
import "@goauthentik/elements/sidebar/Sidebar";
|
||||||
import "@goauthentik/elements/sidebar/SidebarItem";
|
import "@goauthentik/elements/sidebar/SidebarItem";
|
||||||
|
import { UserManagerSettings } from "oidc-client-ts";
|
||||||
|
|
||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
@ -48,6 +50,10 @@ export class AdminInterface extends OAuthInterface {
|
||||||
@state()
|
@state()
|
||||||
user?: SessionUser;
|
user?: SessionUser;
|
||||||
|
|
||||||
|
get oauthSettings(): UserManagerSettings {
|
||||||
|
return adminSettings;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
PFBase,
|
PFBase,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import "@goauthentik/admin/admin-overview/AdminOverviewPage";
|
import "@goauthentik/admin/admin-overview/AdminOverviewPage";
|
||||||
import "@goauthentik/app/common/oauth/callback";
|
import "@goauthentik/app/common/oauth/callback";
|
||||||
|
import { adminSettings } from "@goauthentik/app/common/oauth/settings";
|
||||||
import "@goauthentik/app/common/oauth/signout";
|
import "@goauthentik/app/common/oauth/signout";
|
||||||
import { ID_REGEX, Route, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
import { ID_REGEX, Route, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
||||||
|
|
||||||
|
@ -11,10 +12,13 @@ export const ROUTES: Route[] = [
|
||||||
new Route(new RegExp("^#.*")).redirect("/administration/overview"),
|
new Route(new RegExp("^#.*")).redirect("/administration/overview"),
|
||||||
new Route(new RegExp("^/library$")).redirect("/if/user/", true),
|
new Route(new RegExp("^/library$")).redirect("/if/user/", true),
|
||||||
new Route(new RegExp("^/oauth-callback/(?<rest>.*)$"), async (args) => {
|
new Route(new RegExp("^/oauth-callback/(?<rest>.*)$"), async (args) => {
|
||||||
return html`<ak-oauth-callback params=${args.rest}></ak-oauth-callback>`;
|
return html`<ak-oauth-callback
|
||||||
|
.settings=${adminSettings}
|
||||||
|
params=${args.rest}
|
||||||
|
></ak-oauth-callback>`;
|
||||||
}),
|
}),
|
||||||
new Route(new RegExp("^/oauth-signout$"), async () => {
|
new Route(new RegExp("^/oauth-signout$"), async () => {
|
||||||
return html`<ak-oauth-signout></ak-oauth-signout>`;
|
return html`<ak-oauth-signout .settings=${adminSettings}></ak-oauth-signout>`;
|
||||||
}),
|
}),
|
||||||
// statically imported since this is the default route
|
// statically imported since this is the default route
|
||||||
new Route(new RegExp("^/administration/overview$"), async () => {
|
new Route(new RegExp("^/administration/overview$"), async () => {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { state } from "@goauthentik/app/common/oauth/constants";
|
import { state } from "@goauthentik/app/common/oauth/constants";
|
||||||
import { settings } from "@goauthentik/app/common/oauth/settings";
|
|
||||||
import { refreshMe } from "@goauthentik/app/common/users";
|
import { refreshMe } from "@goauthentik/app/common/users";
|
||||||
import { User, UserManager } from "oidc-client-ts";
|
import { User, UserManager, UserManagerSettings } from "oidc-client-ts";
|
||||||
|
|
||||||
import { LitElement } from "lit";
|
import { LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
@ -10,8 +9,13 @@ import { customElement, property } from "lit/decorators.js";
|
||||||
export class OAuthCallback extends LitElement {
|
export class OAuthCallback extends LitElement {
|
||||||
@property()
|
@property()
|
||||||
params?: string;
|
params?: string;
|
||||||
|
@property({ attribute: false })
|
||||||
|
settings?: UserManagerSettings;
|
||||||
async firstUpdated(): Promise<void> {
|
async firstUpdated(): Promise<void> {
|
||||||
const client = new UserManager(settings);
|
if (!this.settings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = new UserManager(this.settings);
|
||||||
const user = (await client.signinCallback(`#${this.params}`)) as User;
|
const user = (await client.signinCallback(`#${this.params}`)) as User;
|
||||||
const st = user.state as state;
|
const st = user.state as state;
|
||||||
window.location.assign(st.url);
|
window.location.assign(st.url);
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import { state } from "@goauthentik/app/common/oauth/constants";
|
import { state } from "@goauthentik/app/common/oauth/constants";
|
||||||
import { settings } from "@goauthentik/app/common/oauth/settings";
|
|
||||||
import { Interface } from "@goauthentik/app/elements/Base";
|
import { Interface } from "@goauthentik/app/elements/Base";
|
||||||
import { UserManager } from "oidc-client-ts";
|
import { UserManager, UserManagerSettings } from "oidc-client-ts";
|
||||||
|
|
||||||
|
export abstract class OAuthInterface extends Interface {
|
||||||
|
abstract get oauthSettings(): UserManagerSettings;
|
||||||
|
|
||||||
export class OAuthInterface extends Interface {
|
|
||||||
private async ensureLoggedIn() {
|
private async ensureLoggedIn() {
|
||||||
const client = new UserManager(settings);
|
const client = new UserManager(this.oauthSettings);
|
||||||
const user = await client.getUser();
|
const user = await client.getUser();
|
||||||
if (user !== null) {
|
if (user !== null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (window.location.href.startsWith(settings.redirect_uri)) {
|
if (window.location.href.startsWith(this.oauthSettings.redirect_uri)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const s = new state();
|
const s = new state();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { settings } from "@goauthentik/app/common/oauth/settings";
|
import { adminSettings } from "@goauthentik/app/common/oauth/settings";
|
||||||
import { UserManager } from "oidc-client-ts";
|
import { UserManager } from "oidc-client-ts";
|
||||||
|
|
||||||
import { FetchParams, Middleware, RequestContext } from "@goauthentik/api";
|
import { FetchParams, Middleware, RequestContext } from "@goauthentik/api";
|
||||||
|
|
||||||
export class TokenMiddleware implements Middleware {
|
export class TokenMiddleware implements Middleware {
|
||||||
async pre?(context: RequestContext): Promise<FetchParams | void> {
|
async pre?(context: RequestContext): Promise<FetchParams | void> {
|
||||||
const user = await new UserManager(settings).getUser();
|
const user = await new UserManager(adminSettings).getUser();
|
||||||
if (user !== null) {
|
if (user !== null) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
context.init.headers["Authorization"] = `Bearer ${user.access_token}`;
|
context.init.headers["Authorization"] = `Bearer ${user.access_token}`;
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
|
import { MemoryStore } from "@goauthentik/app/common/oauth/storage";
|
||||||
import { Log, OidcClientSettings, UserManagerSettings } from "oidc-client-ts";
|
import { Log, OidcClientSettings, UserManagerSettings } from "oidc-client-ts";
|
||||||
|
|
||||||
Log.setLogger(console);
|
Log.setLogger(console);
|
||||||
Log.setLevel(Log.DEBUG);
|
Log.setLevel(Log.DEBUG);
|
||||||
|
|
||||||
export const settings: OidcClientSettings & UserManagerSettings = {
|
export const userSettings: OidcClientSettings & UserManagerSettings = {
|
||||||
|
authority: `${window.location.origin}/application/o/authentik-user-interface/`,
|
||||||
|
redirect_uri: `${window.location.origin}/if/user/#/oauth-callback/`,
|
||||||
|
client_id: "authentik-user-interface",
|
||||||
|
scope: "openid profile email goauthentik.io/api",
|
||||||
|
response_mode: "fragment",
|
||||||
|
automaticSilentRenew: true,
|
||||||
|
userStore: new MemoryStore(),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const adminSettings: OidcClientSettings & UserManagerSettings = {
|
||||||
authority: `${window.location.origin}/application/o/authentik-admin-interface/`,
|
authority: `${window.location.origin}/application/o/authentik-admin-interface/`,
|
||||||
redirect_uri: `${window.location.origin}/if/admin/#/oauth-callback/`,
|
redirect_uri: `${window.location.origin}/if/admin/#/oauth-callback/`,
|
||||||
client_id: "authentik-admin-interface",
|
client_id: "authentik-admin-interface",
|
||||||
scope: "openid profile email goauthentik.io/api",
|
scope: "openid profile email goauthentik.io/api",
|
||||||
response_mode: "fragment",
|
response_mode: "fragment",
|
||||||
automaticSilentRenew: true,
|
automaticSilentRenew: true,
|
||||||
|
userStore: new MemoryStore(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import { settings } from "@goauthentik/app/common/oauth/settings";
|
import { UserManager, UserManagerSettings } from "oidc-client-ts";
|
||||||
import { UserManager } from "oidc-client-ts";
|
|
||||||
|
|
||||||
import { LitElement } from "lit";
|
import { LitElement } from "lit";
|
||||||
import { customElement } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
|
||||||
@customElement("ak-oauth-signout")
|
@customElement("ak-oauth-signout")
|
||||||
export class OAuthSignout extends LitElement {
|
export class OAuthSignout extends LitElement {
|
||||||
|
@property({ attribute: false })
|
||||||
|
settings?: UserManagerSettings;
|
||||||
async firstUpdated(): Promise<void> {
|
async firstUpdated(): Promise<void> {
|
||||||
const client = new UserManager(settings);
|
if (!this.settings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const client = new UserManager(this.settings);
|
||||||
await client.signoutRedirect();
|
await client.signoutRedirect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
web/src/common/oauth/storage.ts
Normal file
20
web/src/common/oauth/storage.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { WebStorageStateStore } from "oidc-client-ts";
|
||||||
|
|
||||||
|
export class MemoryStore extends WebStorageStateStore {
|
||||||
|
private map: Map<string, string> = new Map();
|
||||||
|
async set(key: string, value: string): Promise<void> {
|
||||||
|
this.map.set(key, value);
|
||||||
|
}
|
||||||
|
async get(key: string): Promise<string | null> {
|
||||||
|
const value = this.map.get(key);
|
||||||
|
return value ? value : null;
|
||||||
|
}
|
||||||
|
async remove(key: string): Promise<string | null> {
|
||||||
|
const value = await this.get(key);
|
||||||
|
this.map.delete(key);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async getAllKeys(): Promise<string[]> {
|
||||||
|
return Array.from(this.map.keys());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import "@goauthentik/app/common/oauth/callback";
|
import "@goauthentik/app/common/oauth/callback";
|
||||||
|
import { userSettings } from "@goauthentik/app/common/oauth/settings";
|
||||||
import "@goauthentik/app/common/oauth/signout";
|
import "@goauthentik/app/common/oauth/signout";
|
||||||
import { Route } from "@goauthentik/elements/router/Route";
|
import { Route } from "@goauthentik/elements/router/Route";
|
||||||
import "@goauthentik/user/LibraryPage/LibraryPage";
|
import "@goauthentik/user/LibraryPage/LibraryPage";
|
||||||
|
@ -10,10 +11,13 @@ export const ROUTES: Route[] = [
|
||||||
new Route(new RegExp("^/$")).redirect("/library"),
|
new Route(new RegExp("^/$")).redirect("/library"),
|
||||||
new Route(new RegExp("^#.*")).redirect("/library"),
|
new Route(new RegExp("^#.*")).redirect("/library"),
|
||||||
new Route(new RegExp("^/oauth-callback/(?<rest>.*)$"), async (args) => {
|
new Route(new RegExp("^/oauth-callback/(?<rest>.*)$"), async (args) => {
|
||||||
return html`<ak-oauth-callback params=${args.rest}></ak-oauth-callback>`;
|
return html`<ak-oauth-callback
|
||||||
|
.settings=${userSettings}
|
||||||
|
params=${args.rest}
|
||||||
|
></ak-oauth-callback>`;
|
||||||
}),
|
}),
|
||||||
new Route(new RegExp("^/oauth-signout$"), async () => {
|
new Route(new RegExp("^/oauth-signout$"), async () => {
|
||||||
return html`<ak-oauth-signout></ak-oauth-signout>`;
|
return html`<ak-oauth-signout .settings=${userSettings}></ak-oauth-signout>`;
|
||||||
}),
|
}),
|
||||||
new Route(new RegExp("^/library$"), async () => html`<ak-library></ak-library>`),
|
new Route(new RegExp("^/library$"), async () => html`<ak-library></ak-library>`),
|
||||||
new Route(new RegExp("^/settings$"), async () => {
|
new Route(new RegExp("^/settings$"), async () => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { OAuthInterface } from "@goauthentik/app/common/oauth/interface";
|
import { OAuthInterface } from "@goauthentik/app/common/oauth/interface";
|
||||||
|
import { userSettings } from "@goauthentik/app/common/oauth/settings";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import {
|
import {
|
||||||
EVENT_API_DRAWER_TOGGLE,
|
EVENT_API_DRAWER_TOGGLE,
|
||||||
|
@ -23,6 +24,7 @@ import { DefaultTenant } from "@goauthentik/elements/sidebar/SidebarBrand";
|
||||||
import "@goauthentik/elements/sidebar/SidebarItem";
|
import "@goauthentik/elements/sidebar/SidebarItem";
|
||||||
import { ROUTES } from "@goauthentik/user/Routes";
|
import { ROUTES } from "@goauthentik/user/Routes";
|
||||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||||
|
import { UserManagerSettings } from "oidc-client-ts";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
|
@ -56,6 +58,10 @@ export class UserInterface extends OAuthInterface {
|
||||||
@state()
|
@state()
|
||||||
me?: SessionUser;
|
me?: SessionUser;
|
||||||
|
|
||||||
|
get oauthSettings(): UserManagerSettings {
|
||||||
|
return userSettings;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
PFBase,
|
PFBase,
|
||||||
|
|
Reference in a new issue