Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [AUTH-1697] (BREAKING) Refactor authenticateJwt and authenticateJwtLocal to use request pattern #253

Merged
merged 4 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions dist/b2b/sessions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 13 additions & 8 deletions dist/b2c/sessions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions lib/b2b/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

// MANUAL(exports)(TYPES)
export type { SearchQueryOperand } from "./organizations";
export type {
B2BSessionsAuthenticateJwtRequest,
B2BSessionsAuthenticateJwtLocalRequest,
} from "./sessions";
// ENDMANUAL(exports)

export type { MemberOptions, MfaRequired } from "./mfa";
Expand Down
73 changes: 58 additions & 15 deletions lib/b2b/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,52 @@ export interface B2BSessionsRevokeResponse {
status_code: number;
}

// MANUAL(authenticateJwt)(TYPES)

// Request type for `sessions.authenticateJwt`
export interface B2BSessionsAuthenticateJwtRequest {
/**
* The JWT to authenticate. You may provide a JWT that has expired according to its `exp` claim and needs
* to be refreshed. If the signature is valid and the underlying session is still active then Stytch will
* return a new JWT.
*/
session_jwt: string;

/**
* If set, remote verification will be forced if the JWT was issued at (based on the "iat" claim) more than that many seconds ago.
* If explicitly set to zero, all tokens will be considered too old, even if they are otherwise valid.
*/
max_token_age_seconds?: number;
}

// Request type for `sessions.authenticateJwtLocal`
export interface B2BSessionsAuthenticateJwtLocalRequest {
/**
* The JWT to authenticate. The JWT must not be expired in order for this request to succeed.
*/
session_jwt: string;

/**
* The maximum allowable difference when comparing timestamps.
* It defaults to zero.
*/
clock_tolerance_seconds?: number;

/**
* If set, return an error if the JWT was issued (based on the "iat" claim) more than max_token_age_seconds seconds ago.
* If explicitly set to zero, all tokens will be considered too old, even if they are otherwise valid.
*/
max_token_age_seconds?: number;

/**
* The value used to compare timestamp claims ("exp", "nbf", "iat").
* It defaults to the current date (new Date()).
*/
current_date?: Date;
}

// ENDMANUAL(authenticateJwt)

export class Sessions {
private fetchConfig: fetchConfig;
private jwksClient: jose.JWTVerifyGetKey;
Expand Down Expand Up @@ -434,20 +480,17 @@ export class Sessions {
* authenticate method instead.
*/
async authenticateJwt(
jwt: string,
options?: {
max_token_age_seconds?: number;
}
params: B2BSessionsAuthenticateJwtRequest
): Promise<{ member_session: MemberSession; session_jwt: string }> {
try {
const member_session = await this.authenticateJwtLocal(jwt, options);
const member_session = await this.authenticateJwtLocal(params);
return {
member_session,
session_jwt: jwt,
session_jwt: params.session_jwt,
};
} catch (err) {
// JWT could not be verified locally. Check with the Stytch API.
return this.authenticate({ session_jwt: jwt });
return this.authenticate({ session_jwt: params.session_jwt });
}
}

Expand All @@ -466,18 +509,17 @@ export class Sessions {
* timestamps. It defaults to zero.
*/
async authenticateJwtLocal(
jwt: string,
options?: {
clock_tolerance_seconds?: number;
max_token_age_seconds?: number;
current_date?: Date;
}
params: B2BSessionsAuthenticateJwtLocalRequest
): Promise<MemberSession> {
const sess = await authenticateSessionJwtLocal(
this.jwksClient,
this.jwtOptions,
jwt,
options
params.session_jwt,
{
clock_tolerance_seconds: params.clock_tolerance_seconds,
max_token_age_seconds: params.max_token_age_seconds,
current_date: params.current_date,
}
);

const organizationClaim = "https://stytch.com/organization";
Expand All @@ -498,5 +540,6 @@ export class Sessions {
custom_claims: claims,
};
}

// ENDMANUAL(authenticateJwt)
}
5 changes: 5 additions & 0 deletions lib/b2c/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
// MANUAL(exports)(TYPES)
export type { SearchUsersQueryOperand } from "./users";

export type {
SessionsAuthenticateJwtRequest,
SessionsAuthenticateJwtLocalRequest,
} from "./sessions";

export type {
AuthenticateTokenRequest,
AuthenticateTokenResponse,
Expand Down
76 changes: 59 additions & 17 deletions lib/b2c/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,52 @@ export interface SessionsRevokeResponse {
status_code: number;
}

// MANUAL(authenticateJwt)(TYPES)

// Request type for `sessions.authenticateJwt`
export interface SessionsAuthenticateJwtRequest {
/**
* The JWT to authenticate. You may provide a JWT that has expired according to its `exp` claim and needs
* to be refreshed. If the signature is valid and the underlying session is still active then Stytch will
* return a new JWT.
*/
session_jwt: string;

/**
* If set, remote verification will be forced if the JWT was issued at (based on the "iat" claim) more than that many seconds ago.
* If explicitly set to zero, all tokens will be considered too old, even if they are otherwise valid.
*/
max_token_age_seconds?: number;
}

// Request type for `sessions.authenticateJwtLocal`
export interface SessionsAuthenticateJwtLocalRequest {
/**
* The JWT to authenticate. The JWT must not be expired in order for this request to succeed.
*/
session_jwt: string;

/**
* The maximum allowable difference when comparing timestamps.
* It defaults to zero.
*/
clock_tolerance_seconds?: number;

/**
* If set, return an error if the JWT was issued (based on the "iat" claim) more than max_token_age_seconds seconds ago.
* If explicitly set to zero, all tokens will be considered too old, even if they are otherwise valid.
*/
max_token_age_seconds?: number;

/**
* The value used to compare timestamp claims ("exp", "nbf", "iat").
* It defaults to the current date (new Date()).
*/
current_date?: Date;
}

// ENDMANUAL(authenticateJwt)

export class Sessions {
private fetchConfig: fetchConfig;
private jwksClient: jose.JWTVerifyGetKey;
Expand Down Expand Up @@ -605,27 +651,24 @@ export class Sessions {
* authenticate method instead.
*/
async authenticateJwt(
jwt: string,
options?: {
max_token_age_seconds?: number;
}
params: SessionsAuthenticateJwtRequest
): Promise<{ session: Session; session_jwt: string }> {
try {
const session = await this.authenticateJwtLocal(jwt, options);
const session = await this.authenticateJwtLocal(params);
return {
session,
session_jwt: jwt,
session_jwt: params.session_jwt,
};
} catch (err) {
// JWT could not be verified locally. Check with the Stytch API.
return this.authenticate({ session_jwt: jwt });
return this.authenticate({ session_jwt: params.session_jwt });
}
}

/** Parse a JWT and verify the signature locally (without calling /authenticate in the API).
*
* If maxTokenAge is set, this will return an error if the JWT was issued (based on the "iat"
* claim) more than maxTokenAge seconds ago.
* If max_token_age_seconds is set, this will return an error if the JWT was issued (based on the "iat"
* claim) more than max_token_age_seconds seconds ago.
*
* If max_token_age_seconds is explicitly set to zero, all tokens will be considered too old,
* even if they are otherwise valid.
Expand All @@ -637,18 +680,17 @@ export class Sessions {
* timestamps. It defaults to zero.
*/
async authenticateJwtLocal(
jwt: string,
options?: {
clock_tolerance_seconds?: number;
max_token_age_seconds?: number;
current_date?: Date;
}
params: SessionsAuthenticateJwtLocalRequest
): Promise<Session> {
const sess = await authenticateSessionJwtLocal(
this.jwksClient,
this.jwtOptions,
jwt,
options
params.session_jwt,
{
clock_tolerance_seconds: params.clock_tolerance_seconds,
max_token_age_seconds: params.max_token_age_seconds,
current_date: params.current_date,
}
);

return {
Expand Down
Loading
Loading