mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 04:46:05 +00:00
added format command and added trailing commas to reduce conflicts
This commit is contained in:
@@ -4,7 +4,7 @@ import {
|
||||
Authenticator,
|
||||
type ProfileExchange,
|
||||
Role,
|
||||
type Strategy
|
||||
type Strategy,
|
||||
} from "auth";
|
||||
import type { PasswordStrategy } from "auth/authenticate/strategies";
|
||||
import { type DB, Exception, type PrimaryFieldType } from "core";
|
||||
@@ -68,15 +68,15 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Could not build strategy ${String(
|
||||
name
|
||||
)} with config ${JSON.stringify(strategy.config)}`
|
||||
name,
|
||||
)} with config ${JSON.stringify(strategy.config)}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this._authenticator = new Authenticator(strategies, this.resolveUser.bind(this), {
|
||||
jwt: this.config.jwt,
|
||||
cookie: this.config.cookie
|
||||
cookie: this.config.cookie,
|
||||
});
|
||||
|
||||
this.registerEntities();
|
||||
@@ -117,7 +117,7 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
action: AuthAction,
|
||||
strategy: Strategy,
|
||||
identifier: string,
|
||||
profile: ProfileExchange
|
||||
profile: ProfileExchange,
|
||||
): Promise<any> {
|
||||
if (!this.config.allow_register && action === "register") {
|
||||
throw new Exception("Registration is not allowed", 403);
|
||||
@@ -127,7 +127,7 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
.getFillableFields("create")
|
||||
.map((f) => f.name);
|
||||
const filteredProfile = Object.fromEntries(
|
||||
Object.entries(profile).filter(([key]) => fields.includes(key))
|
||||
Object.entries(profile).filter(([key]) => fields.includes(key)),
|
||||
);
|
||||
|
||||
switch (action) {
|
||||
@@ -190,7 +190,7 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
const payload: any = {
|
||||
...profile,
|
||||
strategy: strategy.getName(),
|
||||
strategy_value: identifier
|
||||
strategy_value: identifier,
|
||||
};
|
||||
|
||||
const mutator = this.em.mutator(users);
|
||||
@@ -240,13 +240,13 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
email: text().required(),
|
||||
strategy: text({
|
||||
fillable: ["create"],
|
||||
hidden: ["update", "form"]
|
||||
hidden: ["update", "form"],
|
||||
}).required(),
|
||||
strategy_value: text({
|
||||
fillable: ["create"],
|
||||
hidden: ["read", "table", "update", "form"]
|
||||
hidden: ["read", "table", "update", "form"],
|
||||
}).required(),
|
||||
role: text()
|
||||
role: text(),
|
||||
};
|
||||
|
||||
registerEntities() {
|
||||
@@ -254,12 +254,12 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
this.ensureSchema(
|
||||
em(
|
||||
{
|
||||
[users.name as "users"]: users
|
||||
[users.name as "users"]: users,
|
||||
},
|
||||
({ index }, { users }) => {
|
||||
index(users).on(["email"], true).on(["strategy"]).on(["strategy_value"]);
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -288,7 +288,7 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
...(additional as any),
|
||||
email,
|
||||
strategy,
|
||||
strategy_value
|
||||
strategy_value,
|
||||
});
|
||||
mutator.__unstable_toggleSystemEntityCreation(true);
|
||||
return created;
|
||||
@@ -307,8 +307,8 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
strategies: transformObject(strategies, (strategy) => ({
|
||||
enabled: this.isStrategyEnabled(strategy),
|
||||
type: strategy.getType(),
|
||||
config: strategy.toJSON(secrets)
|
||||
}))
|
||||
config: strategy.toJSON(secrets),
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ export type AuthApiOptions = BaseModuleApiOptions & {
|
||||
export class AuthApi extends ModuleApi<AuthApiOptions> {
|
||||
protected override getDefaultOptions(): Partial<AuthApiOptions> {
|
||||
return {
|
||||
basepath: "/api/auth"
|
||||
basepath: "/api/auth",
|
||||
};
|
||||
}
|
||||
|
||||
async login(strategy: string, input: any) {
|
||||
const res = await this.post<AuthResponse>([strategy, "login"], input, {
|
||||
credentials: "include"
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (res.ok && res.body.token) {
|
||||
@@ -27,7 +27,7 @@ export class AuthApi extends ModuleApi<AuthApiOptions> {
|
||||
|
||||
async register(strategy: string, input: any) {
|
||||
const res = await this.post<AuthResponse>([strategy, "register"], input, {
|
||||
credentials: "include"
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (res.ok && res.body.token) {
|
||||
|
||||
@@ -58,7 +58,7 @@ export class AuthController extends Controller {
|
||||
try {
|
||||
const body = await this.auth.authenticator.getBody(c);
|
||||
const valid = parse(create.schema, body, {
|
||||
skipMark: true
|
||||
skipMark: true,
|
||||
});
|
||||
const processed = (await create.preprocess?.(valid)) ?? valid;
|
||||
|
||||
@@ -67,7 +67,7 @@ export class AuthController extends Controller {
|
||||
mutator.__unstable_toggleSystemEntityCreation(false);
|
||||
const { data: created } = await mutator.insertOne({
|
||||
...processed,
|
||||
strategy: name
|
||||
strategy: name,
|
||||
});
|
||||
mutator.__unstable_toggleSystemEntityCreation(true);
|
||||
|
||||
@@ -75,21 +75,21 @@ export class AuthController extends Controller {
|
||||
success: true,
|
||||
action: "create",
|
||||
strategy: name,
|
||||
data: created as unknown as SafeUser
|
||||
data: created as unknown as SafeUser,
|
||||
} as AuthActionResponse);
|
||||
} catch (e) {
|
||||
if (e instanceof TypeInvalidError) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
errors: e.errors
|
||||
errors: e.errors,
|
||||
},
|
||||
400
|
||||
400,
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
hono.get("create/schema.json", async (c) => {
|
||||
return c.json(create.schema);
|
||||
@@ -147,12 +147,12 @@ export class AuthController extends Controller {
|
||||
strategies: transformObject(strategies ?? {}, (strategy, name) => {
|
||||
return this.auth.isStrategyEnabled(name) ? strategy : undefined;
|
||||
}),
|
||||
basepath
|
||||
basepath,
|
||||
});
|
||||
}
|
||||
|
||||
return c.json({ strategies, basepath });
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return hono.all("*", (c) => c.notFound());
|
||||
|
||||
@@ -5,16 +5,16 @@ import { type Static, StringRecord, Type, objectTransform } from "core/utils";
|
||||
export const Strategies = {
|
||||
password: {
|
||||
cls: PasswordStrategy,
|
||||
schema: PasswordStrategy.prototype.getSchema()
|
||||
schema: PasswordStrategy.prototype.getSchema(),
|
||||
},
|
||||
oauth: {
|
||||
cls: OAuthStrategy,
|
||||
schema: OAuthStrategy.prototype.getSchema()
|
||||
schema: OAuthStrategy.prototype.getSchema(),
|
||||
},
|
||||
custom_oauth: {
|
||||
cls: CustomOAuthStrategy,
|
||||
schema: CustomOAuthStrategy.prototype.getSchema()
|
||||
}
|
||||
schema: CustomOAuthStrategy.prototype.getSchema(),
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const STRATEGIES = Strategies;
|
||||
@@ -23,12 +23,12 @@ const strategiesSchemaObject = objectTransform(STRATEGIES, (strategy, name) => {
|
||||
{
|
||||
enabled: Type.Optional(Type.Boolean({ default: true })),
|
||||
type: Type.Const(name, { default: name, readOnly: true }),
|
||||
config: strategy.schema
|
||||
config: strategy.schema,
|
||||
},
|
||||
{
|
||||
title: name,
|
||||
additionalProperties: false
|
||||
}
|
||||
additionalProperties: false,
|
||||
},
|
||||
);
|
||||
});
|
||||
const strategiesSchema = Type.Union(Object.values(strategiesSchemaObject));
|
||||
@@ -37,15 +37,15 @@ export type AppAuthOAuthStrategy = Static<typeof STRATEGIES.oauth.schema>;
|
||||
export type AppAuthCustomOAuthStrategy = Static<typeof STRATEGIES.custom_oauth.schema>;
|
||||
|
||||
const guardConfigSchema = Type.Object({
|
||||
enabled: Type.Optional(Type.Boolean({ default: false }))
|
||||
enabled: Type.Optional(Type.Boolean({ default: false })),
|
||||
});
|
||||
export const guardRoleSchema = Type.Object(
|
||||
{
|
||||
permissions: Type.Optional(Type.Array(Type.String())),
|
||||
is_default: Type.Optional(Type.Boolean()),
|
||||
implicit_allow: Type.Optional(Type.Boolean())
|
||||
implicit_allow: Type.Optional(Type.Boolean()),
|
||||
},
|
||||
{ additionalProperties: false }
|
||||
{ additionalProperties: false },
|
||||
);
|
||||
|
||||
export const authConfigSchema = Type.Object(
|
||||
@@ -64,19 +64,19 @@ export const authConfigSchema = Type.Object(
|
||||
type: "password",
|
||||
enabled: true,
|
||||
config: {
|
||||
hashing: "sha256"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
hashing: "sha256",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
guard: Type.Optional(guardConfigSchema),
|
||||
roles: Type.Optional(StringRecord(guardRoleSchema, { default: {} }))
|
||||
roles: Type.Optional(StringRecord(guardRoleSchema, { default: {} })),
|
||||
},
|
||||
{
|
||||
title: "Authentication",
|
||||
additionalProperties: false
|
||||
}
|
||||
additionalProperties: false,
|
||||
},
|
||||
);
|
||||
|
||||
export type AppAuthSchema = Static<typeof authConfigSchema>;
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
Type,
|
||||
parse,
|
||||
runtimeSupports,
|
||||
transformObject
|
||||
transformObject,
|
||||
} from "core/utils";
|
||||
import type { Context, Hono } from "hono";
|
||||
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
|
||||
@@ -71,9 +71,9 @@ export const cookieConfig = Type.Partial(
|
||||
expires: Type.Number({ default: defaultCookieExpires }), // seconds
|
||||
renew: Type.Boolean({ default: true }),
|
||||
pathSuccess: Type.String({ default: "/" }),
|
||||
pathLoggedOut: Type.String({ default: "/" })
|
||||
pathLoggedOut: Type.String({ default: "/" }),
|
||||
}),
|
||||
{ default: {}, additionalProperties: false }
|
||||
{ default: {}, additionalProperties: false },
|
||||
);
|
||||
|
||||
// @todo: maybe add a config to not allow cookie/api tokens to be used interchangably?
|
||||
@@ -86,16 +86,16 @@ export const jwtConfig = Type.Object(
|
||||
alg: Type.Optional(StringEnum(["HS256", "HS384", "HS512"], { default: "HS256" })),
|
||||
expires: Type.Optional(Type.Number()), // seconds
|
||||
issuer: Type.Optional(Type.String()),
|
||||
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] })
|
||||
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] }),
|
||||
},
|
||||
{
|
||||
default: {},
|
||||
additionalProperties: false
|
||||
}
|
||||
additionalProperties: false,
|
||||
},
|
||||
);
|
||||
export const authenticatorConfig = Type.Object({
|
||||
jwt: jwtConfig,
|
||||
cookie: cookieConfig
|
||||
cookie: cookieConfig,
|
||||
});
|
||||
|
||||
type AuthConfig = Static<typeof authenticatorConfig>;
|
||||
@@ -104,7 +104,7 @@ export type AuthUserResolver = (
|
||||
action: AuthAction,
|
||||
strategy: Strategy,
|
||||
identifier: string,
|
||||
profile: ProfileExchange
|
||||
profile: ProfileExchange,
|
||||
) => Promise<SafeUser | undefined>;
|
||||
type AuthClaims = SafeUser & {
|
||||
iat: number;
|
||||
@@ -127,7 +127,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
action: AuthAction,
|
||||
strategy: Strategy,
|
||||
identifier: string,
|
||||
profile: ProfileExchange
|
||||
profile: ProfileExchange,
|
||||
): Promise<AuthResponse> {
|
||||
//console.log("resolve", { action, strategy: strategy.getName(), profile });
|
||||
const user = await this.userResolver(action, strategy, identifier, profile);
|
||||
@@ -135,7 +135,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
if (user) {
|
||||
return {
|
||||
user,
|
||||
token: await this.jwt(user)
|
||||
token: await this.jwt(user),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
|
||||
strategy<
|
||||
StrategyName extends keyof Strategies,
|
||||
Strat extends Strategy = Strategies[StrategyName]
|
||||
Strat extends Strategy = Strategies[StrategyName],
|
||||
>(strategy: StrategyName): Strat {
|
||||
try {
|
||||
return this.strategies[strategy] as unknown as Strat;
|
||||
@@ -168,7 +168,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
|
||||
const payload: JWTPayload = {
|
||||
...user,
|
||||
iat: Math.floor(Date.now() / 1000)
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
};
|
||||
|
||||
// issuer
|
||||
@@ -194,7 +194,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
const payload = await verify(
|
||||
jwt,
|
||||
this.config.jwt?.secret ?? "",
|
||||
this.config.jwt?.alg ?? "HS256"
|
||||
this.config.jwt?.alg ?? "HS256",
|
||||
);
|
||||
|
||||
// manually verify issuer (hono doesn't support it)
|
||||
@@ -215,7 +215,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
|
||||
return {
|
||||
...cookieConfig,
|
||||
expires: new Date(Date.now() + expires * 1000)
|
||||
expires: new Date(Date.now() + expires * 1000),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -342,17 +342,17 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
toJSON(secrets?: boolean) {
|
||||
return {
|
||||
...this.config,
|
||||
jwt: secrets ? this.config.jwt : undefined
|
||||
jwt: secrets ? this.config.jwt : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function createStrategyAction<S extends TObject>(
|
||||
schema: S,
|
||||
preprocess: (input: Static<S>) => Promise<Partial<DB["users"]>>
|
||||
preprocess: (input: Static<S>) => Promise<Partial<DB["users"]>>,
|
||||
) {
|
||||
return {
|
||||
schema,
|
||||
preprocess
|
||||
preprocess,
|
||||
} as StrategyAction<S>;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ type LoginSchema = { username: string; password: string } | { email: string; pas
|
||||
type RegisterSchema = { email: string; password: string; [key: string]: any };
|
||||
|
||||
const schema = Type.Object({
|
||||
hashing: StringEnum(["plain", "sha256" /*, "bcrypt"*/] as const, { default: "sha256" })
|
||||
hashing: StringEnum(["plain", "sha256" /*, "bcrypt"*/] as const, { default: "sha256" }),
|
||||
});
|
||||
|
||||
export type PasswordStrategyOptions = Static<typeof schema>;
|
||||
@@ -49,7 +49,7 @@ export class PasswordStrategy implements Strategy {
|
||||
|
||||
return {
|
||||
...input,
|
||||
password: await this.hash(input.password)
|
||||
password: await this.hash(input.password),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ export class PasswordStrategy implements Strategy {
|
||||
tb(
|
||||
"query",
|
||||
Type.Object({
|
||||
redirect: Type.Optional(Type.String())
|
||||
})
|
||||
redirect: Type.Optional(Type.String()),
|
||||
}),
|
||||
),
|
||||
async (c) => {
|
||||
const body = await authenticator.getBody(c);
|
||||
@@ -75,22 +75,22 @@ export class PasswordStrategy implements Strategy {
|
||||
"login",
|
||||
this,
|
||||
payload.password,
|
||||
payload
|
||||
payload,
|
||||
);
|
||||
|
||||
return await authenticator.respond(c, data, redirect);
|
||||
} catch (e) {
|
||||
return await authenticator.respond(c, e);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.post(
|
||||
"/register",
|
||||
tb(
|
||||
"query",
|
||||
Type.Object({
|
||||
redirect: Type.Optional(Type.String())
|
||||
})
|
||||
redirect: Type.Optional(Type.String()),
|
||||
}),
|
||||
),
|
||||
async (c) => {
|
||||
const body = await authenticator.getBody(c);
|
||||
@@ -101,11 +101,11 @@ export class PasswordStrategy implements Strategy {
|
||||
"register",
|
||||
this,
|
||||
payload.password,
|
||||
payload
|
||||
payload,
|
||||
);
|
||||
|
||||
return await authenticator.respond(c, data, redirect);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,19 +114,19 @@ export class PasswordStrategy implements Strategy {
|
||||
create: createStrategyAction(
|
||||
Type.Object({
|
||||
email: Type.String({
|
||||
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"
|
||||
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$",
|
||||
}),
|
||||
password: Type.String({
|
||||
minLength: 8 // @todo: this should be configurable
|
||||
})
|
||||
minLength: 8, // @todo: this should be configurable
|
||||
}),
|
||||
}),
|
||||
async ({ password, ...input }) => {
|
||||
return {
|
||||
...input,
|
||||
strategy_value: await this.hash(password)
|
||||
strategy_value: await this.hash(password),
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ export {
|
||||
type PasswordStrategyOptions,
|
||||
OAuthStrategy,
|
||||
OAuthCallbackException,
|
||||
CustomOAuthStrategy
|
||||
CustomOAuthStrategy,
|
||||
};
|
||||
|
||||
@@ -15,11 +15,11 @@ const oauthSchemaCustom = Type.Object(
|
||||
{
|
||||
client_id: Type.String(),
|
||||
client_secret: Type.String(),
|
||||
token_endpoint_auth_method: StringEnum(["client_secret_basic"])
|
||||
token_endpoint_auth_method: StringEnum(["client_secret_basic"]),
|
||||
},
|
||||
{
|
||||
additionalProperties: false
|
||||
}
|
||||
additionalProperties: false,
|
||||
},
|
||||
),
|
||||
as: Type.Object(
|
||||
{
|
||||
@@ -29,15 +29,15 @@ const oauthSchemaCustom = Type.Object(
|
||||
scope_separator: Type.Optional(Type.String({ default: " " })),
|
||||
authorization_endpoint: Type.Optional(UrlString),
|
||||
token_endpoint: Type.Optional(UrlString),
|
||||
userinfo_endpoint: Type.Optional(UrlString)
|
||||
userinfo_endpoint: Type.Optional(UrlString),
|
||||
},
|
||||
{
|
||||
additionalProperties: false
|
||||
}
|
||||
)
|
||||
additionalProperties: false,
|
||||
},
|
||||
),
|
||||
// @todo: profile mapping
|
||||
},
|
||||
{ title: "Custom OAuth", additionalProperties: false }
|
||||
{ title: "Custom OAuth", additionalProperties: false },
|
||||
);
|
||||
|
||||
type OAuthConfigCustom = Static<typeof oauthSchemaCustom>;
|
||||
@@ -57,7 +57,7 @@ export type IssuerConfig<UserInfo = any> = {
|
||||
profile: (
|
||||
info: UserInfo,
|
||||
config: Omit<IssuerConfig, "profile">,
|
||||
tokenResponse: any
|
||||
tokenResponse: any,
|
||||
) => Promise<UserProfile>;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,14 +18,14 @@ const schemaProvided = Type.Object(
|
||||
client: Type.Object(
|
||||
{
|
||||
client_id: Type.String(),
|
||||
client_secret: Type.String()
|
||||
client_secret: Type.String(),
|
||||
},
|
||||
{
|
||||
additionalProperties: false
|
||||
}
|
||||
)
|
||||
additionalProperties: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
{ title: "OAuth" }
|
||||
{ title: "OAuth" },
|
||||
);
|
||||
type ProvidedOAuthConfig = Static<typeof schemaProvided>;
|
||||
|
||||
@@ -56,7 +56,7 @@ export type IssuerConfig<UserInfo = any> = {
|
||||
profile: (
|
||||
info: UserInfo,
|
||||
config: Omit<IssuerConfig, "profile">,
|
||||
tokenResponse: any
|
||||
tokenResponse: any,
|
||||
) => Promise<UserProfile>;
|
||||
};
|
||||
|
||||
@@ -65,7 +65,7 @@ export class OAuthCallbackException extends Exception {
|
||||
|
||||
constructor(
|
||||
public error: any,
|
||||
public step: string
|
||||
public step: string,
|
||||
) {
|
||||
super("OAuthCallbackException on " + step);
|
||||
}
|
||||
@@ -103,8 +103,8 @@ export class OAuthStrategy implements Strategy {
|
||||
type: info.type,
|
||||
client: {
|
||||
...info.client,
|
||||
...this._config.client
|
||||
}
|
||||
...this._config.client,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export class OAuthStrategy implements Strategy {
|
||||
|
||||
const { challenge_supported, challenge, challenge_method } = await this.getCodeChallenge(
|
||||
as,
|
||||
options.state
|
||||
options.state,
|
||||
);
|
||||
|
||||
if (!as.authorization_endpoint) {
|
||||
@@ -150,7 +150,7 @@ export class OAuthStrategy implements Strategy {
|
||||
client_id: client.client_id,
|
||||
redirect_uri: options.redirect_uri,
|
||||
response_type: "code",
|
||||
scope: scopes.join(as.scope_separator ?? " ")
|
||||
scope: scopes.join(as.scope_separator ?? " "),
|
||||
};
|
||||
if (challenge_supported) {
|
||||
params.code_challenge = challenge;
|
||||
@@ -162,13 +162,13 @@ export class OAuthStrategy implements Strategy {
|
||||
return {
|
||||
url: new URL(endpoint) + "?" + new URLSearchParams(params).toString(),
|
||||
endpoint,
|
||||
params
|
||||
params,
|
||||
};
|
||||
}
|
||||
|
||||
private async oidc(
|
||||
callbackParams: URL | URLSearchParams,
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] }
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] },
|
||||
) {
|
||||
const config = await this.getConfig();
|
||||
const { client, as, type } = config;
|
||||
@@ -178,7 +178,7 @@ export class OAuthStrategy implements Strategy {
|
||||
as,
|
||||
client, // no client_secret required
|
||||
callbackParams,
|
||||
oauth.expectNoState
|
||||
oauth.expectNoState,
|
||||
);
|
||||
if (oauth.isOAuth2Error(parameters)) {
|
||||
//console.log("callback.error", parameters);
|
||||
@@ -193,7 +193,7 @@ export class OAuthStrategy implements Strategy {
|
||||
client,
|
||||
parameters,
|
||||
options.redirect_uri,
|
||||
options.state
|
||||
options.state,
|
||||
);
|
||||
//console.log("callback.response", response);
|
||||
|
||||
@@ -213,7 +213,7 @@ export class OAuthStrategy implements Strategy {
|
||||
as,
|
||||
client,
|
||||
response,
|
||||
expectedNonce
|
||||
expectedNonce,
|
||||
);
|
||||
if (oauth.isOAuth2Error(result)) {
|
||||
console.log("callback.error", result);
|
||||
@@ -236,7 +236,7 @@ export class OAuthStrategy implements Strategy {
|
||||
|
||||
private async oauth2(
|
||||
callbackParams: URL | URLSearchParams,
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] }
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] },
|
||||
) {
|
||||
const config = await this.getConfig();
|
||||
const { client, type, as, profile } = config;
|
||||
@@ -246,7 +246,7 @@ export class OAuthStrategy implements Strategy {
|
||||
as,
|
||||
client, // no client_secret required
|
||||
callbackParams,
|
||||
oauth.expectNoState
|
||||
oauth.expectNoState,
|
||||
);
|
||||
if (oauth.isOAuth2Error(parameters)) {
|
||||
console.log("callback.error", parameters);
|
||||
@@ -254,14 +254,14 @@ export class OAuthStrategy implements Strategy {
|
||||
}
|
||||
console.log(
|
||||
"callback.parameters",
|
||||
JSON.stringify(Object.fromEntries(parameters.entries()), null, 2)
|
||||
JSON.stringify(Object.fromEntries(parameters.entries()), null, 2),
|
||||
);
|
||||
const response = await oauth.authorizationCodeGrantRequest(
|
||||
as,
|
||||
client,
|
||||
parameters,
|
||||
options.redirect_uri,
|
||||
options.state
|
||||
options.state,
|
||||
);
|
||||
|
||||
const challenges = oauth.parseWwwAuthenticateChallenges(response);
|
||||
@@ -297,7 +297,7 @@ export class OAuthStrategy implements Strategy {
|
||||
|
||||
async callback(
|
||||
callbackParams: URL | URLSearchParams,
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] }
|
||||
options: { redirect_uri: string; state: string; scopes?: string[] },
|
||||
): Promise<UserProfile> {
|
||||
const type = this.getIssuerConfig().type;
|
||||
|
||||
@@ -330,7 +330,7 @@ export class OAuthStrategy implements Strategy {
|
||||
secure: true,
|
||||
httpOnly: true,
|
||||
sameSite: "Lax",
|
||||
maxAge: 60 * 5 // 5 minutes
|
||||
maxAge: 60 * 5, // 5 minutes
|
||||
});
|
||||
};
|
||||
|
||||
@@ -339,7 +339,7 @@ export class OAuthStrategy implements Strategy {
|
||||
return {
|
||||
state: c.req.header("X-State-Challenge"),
|
||||
action: c.req.header("X-State-Action"),
|
||||
mode: "token"
|
||||
mode: "token",
|
||||
} as any;
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ export class OAuthStrategy implements Strategy {
|
||||
|
||||
const profile = await this.callback(params, {
|
||||
redirect_uri,
|
||||
state: state.state
|
||||
state: state.state,
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -392,7 +392,7 @@ export class OAuthStrategy implements Strategy {
|
||||
const params = new URLSearchParams(url.search);
|
||||
|
||||
return c.json({
|
||||
code: params.get("code") ?? null
|
||||
code: params.get("code") ?? null,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -410,7 +410,7 @@ export class OAuthStrategy implements Strategy {
|
||||
const state = oauth.generateRandomCodeVerifier();
|
||||
const response = await this.request({
|
||||
redirect_uri,
|
||||
state
|
||||
state,
|
||||
});
|
||||
//console.log("_state", state);
|
||||
|
||||
@@ -433,7 +433,7 @@ export class OAuthStrategy implements Strategy {
|
||||
const state = oauth.generateRandomCodeVerifier();
|
||||
const response = await this.request({
|
||||
redirect_uri,
|
||||
state
|
||||
state,
|
||||
});
|
||||
|
||||
if (isDebug()) {
|
||||
@@ -442,14 +442,14 @@ export class OAuthStrategy implements Strategy {
|
||||
redirect_uri,
|
||||
challenge: state,
|
||||
action,
|
||||
params: response.params
|
||||
params: response.params,
|
||||
});
|
||||
}
|
||||
|
||||
return c.json({
|
||||
url: response.url,
|
||||
challenge: state,
|
||||
action
|
||||
action,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -477,7 +477,7 @@ export class OAuthStrategy implements Strategy {
|
||||
|
||||
return {
|
||||
type: this.getIssuerConfig().type,
|
||||
...config
|
||||
...config,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export class Guard {
|
||||
implicit_allow?: boolean;
|
||||
}
|
||||
>,
|
||||
config?: GuardConfig
|
||||
config?: GuardConfig,
|
||||
) {
|
||||
const _roles = roles
|
||||
? objectTransform(roles, ({ permissions = [], is_default, implicit_allow }, name) => {
|
||||
@@ -103,7 +103,7 @@ export class Guard {
|
||||
debug &&
|
||||
console.log("guard: role not found", {
|
||||
user: user,
|
||||
role: user?.role
|
||||
role: user?.role,
|
||||
});
|
||||
return this.getDefaultRole();
|
||||
}
|
||||
@@ -141,14 +141,14 @@ export class Guard {
|
||||
}
|
||||
|
||||
const rolePermission = role.permissions.find(
|
||||
(rolePermission) => rolePermission.permission.name === name
|
||||
(rolePermission) => rolePermission.permission.name === name,
|
||||
);
|
||||
|
||||
debug &&
|
||||
console.log("guard: rolePermission, allowing?", {
|
||||
permission: name,
|
||||
role: role.name,
|
||||
allowing: !!rolePermission
|
||||
allowing: !!rolePermission,
|
||||
});
|
||||
return !!rolePermission;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ export class Guard {
|
||||
if (!this.granted(permission, c)) {
|
||||
throw new Exception(
|
||||
`Permission "${typeof permission === "string" ? permission : permission.name}" not granted`,
|
||||
403
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Permission } from "core";
|
||||
export class RolePermission {
|
||||
constructor(
|
||||
public permission: Permission,
|
||||
public config?: any
|
||||
public config?: any,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ export class Role {
|
||||
public name: string,
|
||||
public permissions: RolePermission[] = [],
|
||||
public is_default: boolean = false,
|
||||
public implicit_allow: boolean = false
|
||||
public implicit_allow: boolean = false,
|
||||
) {}
|
||||
|
||||
static createWithPermissionNames(
|
||||
name: string,
|
||||
permissionNames: string[],
|
||||
is_default: boolean = false,
|
||||
implicit_allow: boolean = false
|
||||
implicit_allow: boolean = false,
|
||||
) {
|
||||
return new Role(
|
||||
name,
|
||||
permissionNames.map((name) => new RolePermission(new Permission(name))),
|
||||
is_default,
|
||||
implicit_allow
|
||||
implicit_allow,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export class Role {
|
||||
config.name,
|
||||
config.permissions?.map((name) => new RolePermission(new Permission(name))) ?? [],
|
||||
config.is_default,
|
||||
config.implicit_allow
|
||||
config.implicit_allow,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export {
|
||||
type AuthUserResolver,
|
||||
Authenticator,
|
||||
authenticatorConfig,
|
||||
jwtConfig
|
||||
jwtConfig,
|
||||
} from "./authenticate/Authenticator";
|
||||
|
||||
export { AppAuth, type UserFieldSchema } from "./AppAuth";
|
||||
|
||||
@@ -36,7 +36,7 @@ export const auth = (options?: {
|
||||
registered: false,
|
||||
resolved: false,
|
||||
skip: false,
|
||||
user: undefined
|
||||
user: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export const permission = (
|
||||
options?: {
|
||||
onGranted?: (c: Context<ServerEnv>) => Promise<Response | void | undefined>;
|
||||
onDenied?: (c: Context<ServerEnv>) => Promise<Response | void | undefined>;
|
||||
}
|
||||
},
|
||||
) =>
|
||||
// @ts-ignore
|
||||
createMiddleware<ServerEnv>(async (c, next) => {
|
||||
|
||||
Reference in New Issue
Block a user