Skip to content

Commit

Permalink
Merge pull request #65 from getlarge/64-feat-enable-passing-promises-…
Browse files Browse the repository at this point in the history
…to-resolvers

feat: enable passing promises to resolvers
  • Loading branch information
getlarge authored Jun 4, 2024
2 parents 8687991 + f1b7d85 commit 52445e4
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,28 @@ export interface IOryOAuth2AuthenticationGuard {
}

export interface OryOAuth2AuthenticationGuardOptions {
scopeResolver: (ctx: ExecutionContext) => string;
accessTokenResolver: (ctx: ExecutionContext) => string;
isValidToken: (token: IntrospectedOAuth2Token) => boolean;
scopeResolver: (
this: IOryOAuth2AuthenticationGuard,
ctx: ExecutionContext
) => string | Promise<string>;
accessTokenResolver: (
this: IOryOAuth2AuthenticationGuard,
ctx: ExecutionContext
) => string | Promise<string>;
isValidToken: (
this: IOryOAuth2AuthenticationGuard,
token: IntrospectedOAuth2Token
) => boolean;
postValidationHook?: (
this: IOryOAuth2AuthenticationGuard,
ctx: ExecutionContext,
token: IntrospectedOAuth2Token
) => void | Promise<void>;
unauthorizedFactory: (ctx: ExecutionContext, error: unknown) => Error;
unauthorizedFactory: (
this: IOryOAuth2AuthenticationGuard,
ctx: ExecutionContext,
error: unknown
) => Error;
}

const defaultOptions: OryOAuth2AuthenticationGuardOptions = {
Expand Down Expand Up @@ -59,10 +72,13 @@ export const OryOAuth2AuthenticationGuard = (
...options,
};

const scope = scopeResolver(context);
const token = accessTokenResolver(context);
const scope = await scopeResolver.bind(this)(context);
const token = await accessTokenResolver.bind(this)(context);
if (!token) {
throw unauthorizedFactory(context, new Error('No token provided'));
throw unauthorizedFactory.bind(this)(
context,
new Error('No token provided')
);
}

let decodedToken: IntrospectedOAuth2Token;
Expand All @@ -73,10 +89,13 @@ export const OryOAuth2AuthenticationGuard = (
});
decodedToken = data;
} catch (error) {
throw unauthorizedFactory(context, error);
throw unauthorizedFactory.bind(this)(context, error);
}
if (!isValidToken(decodedToken)) {
throw unauthorizedFactory(context, new Error('Invalid token'));
if (!isValidToken.bind(this)(decodedToken)) {
throw unauthorizedFactory.bind(this)(
context,
new Error('Invalid token')
);
}
if (typeof postValidationHook === 'function') {
await postValidationHook.bind(this)(context, decodedToken);
Expand Down
21 changes: 14 additions & 7 deletions packages/keto-client-wrapper/src/lib/ory-authorization.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@ import {
import { OryPermissionsService } from './ory-permissions';

export interface OryAuthorizationGuardOptions {
errorFactory?: (error: Error) => Error;
postCheck?: (relationTuple: string | string[], isPermitted: boolean) => void;
unauthorizedFactory: (ctx: ExecutionContext, error: unknown) => Error;
postCheck?: (
this: IAuthorizationGuard,
relationTuple: string | string[],
isPermitted: boolean
) => void;
unauthorizedFactory: (
this: IAuthorizationGuard,
ctx: ExecutionContext,
error: unknown
) => Error;
}

export abstract class IAuthorizationGuard implements CanActivate {
Expand Down Expand Up @@ -80,14 +87,14 @@ export const OryAuthorizationGuard = (
);

if (result.hasError()) {
throw unauthorizedFactory(context, result.error);
throw unauthorizedFactory.bind(this)(context, result.error);
}

try {
const { data } = await this.oryService.checkPermission(result.value);
return { allowed: data.allowed, relationTuple };
} catch (error) {
throw unauthorizedFactory(context, error);
throw unauthorizedFactory.bind(this)(context, error);
}
}
const evaluatedConditions = await Promise.all(
Expand Down Expand Up @@ -119,10 +126,10 @@ export const OryAuthorizationGuard = (
);

if (postCheck) {
postCheck(relationTuple, allowed);
postCheck.bind(this)(relationTuple, allowed);
}
if (!allowed) {
throw unauthorizedFactory(
throw unauthorizedFactory.bind(this)(
context,
new Error(`Unauthorized access for ${relationTuple}`)
);
Expand Down
36 changes: 26 additions & 10 deletions packages/kratos-client-wrapper/src/lib/ory-authentication.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,25 @@ export interface IOryAuthenticationGuard {
}

export interface OryAuthenticationGuardOptions {
cookieResolver: (ctx: ExecutionContext) => string;
isValidSession: (session: Session) => boolean;
sessionTokenResolver: (ctx: ExecutionContext) => string;
cookieResolver: (
this: IOryAuthenticationGuard,
ctx: ExecutionContext
) => string | Promise<string>;
isValidSession: (this: IOryAuthenticationGuard, session: Session) => boolean;
sessionTokenResolver: (
this: IOryAuthenticationGuard,
ctx: ExecutionContext
) => string | Promise<string>;
postValidationHook?: (
this: IOryAuthenticationGuard,
ctx: ExecutionContext,
session: Session
) => void | Promise<void>;
unauthorizedFactory: (ctx: ExecutionContext, error: unknown) => Error;
unauthorizedFactory: (
this: IOryAuthenticationGuard,
ctx: ExecutionContext,
error: unknown
) => Error;
}

const defaultOptions: OryAuthenticationGuardOptions = {
Expand Down Expand Up @@ -61,10 +71,13 @@ export const OryAuthenticationGuard = (
...options,
};

const cookie = cookieResolver(context);
const xSessionToken = sessionTokenResolver(context);
const cookie = await cookieResolver.bind(this)(context);
const xSessionToken = await sessionTokenResolver.bind(this)(context);
if (!cookie && !xSessionToken) {
throw unauthorizedFactory(context, new Error('No session token'));
throw unauthorizedFactory.bind(this)(
context,
new Error('No session token')
);
}
let session: Session;
try {
Expand All @@ -74,11 +87,14 @@ export const OryAuthenticationGuard = (
});
session = data;
} catch (error) {
throw unauthorizedFactory(context, error);
throw unauthorizedFactory.bind(this)(context, error);
}

if (!isValidSession(session)) {
throw unauthorizedFactory(context, new Error('Invalid session'));
if (!isValidSession.bind(this)(session)) {
throw unauthorizedFactory.bind(this)(
context,
new Error('Invalid session')
);
}
if (typeof postValidationHook === 'function') {
await postValidationHook.bind(this)(context, session);
Expand Down

0 comments on commit 52445e4

Please sign in to comment.