メインコンテンツまでスキップ
バージョン: 🚧 Canary

🛣️ OAuth routes

OAuth routes are SDK composers, not Express middleware. Provider drivers perform browser redirects; callback routes create a one-time login token and redirect the browser.

Inventory

RouteMethod / protocolPathSchemaValidatorsSuccess status
googleOAuthRouteGET / HTTP/auth/oauth/googlegoogleOauthSchemaNoneDriver redirect
googleOAuthCallbackRouteGET / HTTP/auth/oauth/google/callbackNoneNone302 redirect
lineOAuthRouteGET / HTTP/auth/oauth/linelineOauthSchemaNoneDriver redirect
lineOAuthCallbackRouteGET / HTTP/auth/oauth/line/callbackNoneNone302 redirect
twitterOAuthRouteGET / HTTP/auth/oauth/twittertwitterOauthSchemaNoneDriver redirect
twitterOAuthCallbackRouteGET / HTTP/auth/oauth/twitter/callbackNoneNone302 redirect

Details

googleOAuthRoute

Implementation

Endpoint: GET /auth/oauth/google

Access: Public; validators: [].

Request: googleOauthSchema validates fp, purpose, redirectUrl, optional typeId, and an optional empty JSON object.

Pipeline: requestGoogleOAuthorThrow.

Success: The injected googleOAuthDriver.request handles the provider redirect.

Failure: AuthenticationInvalidTokenError is mapped to 400.

View complete source
export const googleOAuthRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(requestGoogleOAuth, [
['context', 'configuration', 'authSecrets'],
['context', 'googleOAuthDriver', 'request'],
['context', 'request'],
['context', 'response'],
['params', 'requestQuery', 'fp'],
['params', 'requestQuery', 'purpose'],
['params', 'requestQuery', 'redirectUrl'],
['params', 'requestQuery', 'typeId'],
['context', 'configuration', 'onetimeTokenSignOptions'],
]),
),
lift(withLogging(orThrow([[AuthenticationInvalidTokenError, 400]]))),
),
method: 'GET',
path: '/auth/oauth/google',
validators: [],
});

googleOAuthCallbackRoute

Implementation

Endpoint: GET /auth/oauth/google/callback

Access: Public; validators: [].

Request: No composed schema. The route reads provider callback data and requestQuery.state directly.

Pipeline: authenticateGoogleOAuthextractOAuthLoginState → signup-only checkEmailIsUniqueInIdentitiesverifyGoogleOAuthgetLoginTokenTargetgetFingerprintbuildTokenVerificationgenerateOneTimeTokenstoreOneTimeTokengenerateRedirectURLredirectToorThrow.

Success: redirectTo sends 302 to the decoded state redirect URL with onetimeToken appended.

Failure: Invalid token/input is 400, no identity is 404, and database failures are 500. A driver exception before a Result escapes to the service error handler.

View complete source
export const googleOAuthCallbackRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
authenticateGoogleOAuth,
[
['context', 'googleOAuthDriver', 'callback'],
['context', 'request'],
['context', 'response'],
],
'profile',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
extractOAuthLoginState,
[
['context', 'configuration', 'authSecrets'],
['params', 'requestQuery', 'state'],
],
'loginState',
),
),
),
flatMapAsync(
ifElse(
(input: RouteHandlerPayload) => input?.context?.data?.loginState?.purpose === OAUTH_SIGNUP,
withLogging(
applyPayloadArgs(
checkEmailIsUniqueInIdentities,
[
['context', 'db', 'identities'],
['context', 'data', 'profile', 'email'],
],
'isEmailUnique',
),
),
async input => ok(input),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
verifyGoogleOAuth,
[
['context', 'db', 'identities'],
['context', 'data', 'loginState'],
['context', 'data', 'profile'],
],
'identityId',
),
),
),
flatMapAsync(applyPayloadArgs(getLoginTokenTarget, [], 'target')),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['context', 'data', 'tokenVerification'],
['context', 'data', 'identityId'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
storeOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'token'],
],
'isStoredOneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateRedirectURL,
[
['context', 'data', 'token'],
['context', 'data', 'loginState', 'redirectUrl'],
],
'redirectUrl',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(redirectTo, [
['context', 'response'],
['context', 'data', 'redirectUrl'],
]),
),
),
lift(
withLogging(
orThrow([
[AuthenticationInvalidTokenError, 400],
[AuthenticationInvalidInputError, 400],
[AuthenticationNotFoundError, 404],
[AuthenticationUnexpectedDBError, 500],
]),
),
),
),
method: 'GET',
path: '/auth/oauth/google/callback',
validators: [],
});

lineOAuthRoute

Implementation

Endpoint: GET /auth/oauth/line

Access: Public; validators: [].

Request: lineOauthSchema validates fp, purpose, redirectUrl, optional typeId, and an optional empty JSON object.

Pipeline: requestLineOAuthorThrow.

Success: The injected lineOAuthDriver.request handles the provider redirect.

Failure: orThrow([]) has no explicit source error mapping.

View complete source
export const lineOAuthRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
requestLineOAuth,
[
['context', 'configuration', 'authSecrets'],
['context', 'lineOAuthDriver', 'request'],
['context', 'request'],
['context', 'response'],
['params', 'requestQuery', 'fp'],
['params', 'requestQuery', 'purpose'],
['params', 'requestQuery', 'redirectUrl'],
['params', 'requestQuery', 'typeId'],
['context', 'configuration', 'onetimeTokenSignOptions'],
],
'state',
),
),
lift(withLogging(orThrow([]))),
),
method: 'GET',
path: '/auth/oauth/line',
validators: [],
});

lineOAuthCallbackRoute

Implementation

Endpoint: GET /auth/oauth/line/callback

Access: Public; validators: [].

Request: No composed schema; reads provider callback data and requestQuery.state.

Pipeline: authenticateLineOAuthextractOAuthLoginStateverifyLineOAuthgetLoginTokenTargetgetFingerprintbuildTokenVerificationgenerateOneTimeTokenstoreOneTimeTokengenerateRedirectURLredirectToorThrow.

Success: 302 redirect with the generated onetimeToken.

Failure: Input 400, missing identity 404, database or OAuth error 500; a thrown driver callback bypasses its Result wrapper.

View complete source
export const lineOAuthCallbackRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
authenticateLineOAuth,
[
['context', 'lineOAuthDriver', 'callback'],
['context', 'request'],
['context', 'response'],
],
'profile',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
extractOAuthLoginState,
[
['context', 'configuration', 'authSecrets'],
['params', 'requestQuery', 'state'],
],
'loginState',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
verifyLineOAuth,
[
['context', 'db', 'identities'],
['context', 'data', 'loginState'],
['context', 'data', 'profile'],
],
'identityId',
),
),
),
flatMapAsync(applyPayloadArgs(getLoginTokenTarget, [], 'target')),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['context', 'data', 'tokenVerification'],
['context', 'data', 'identityId'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
storeOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'token'],
],
'isStoredOneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateRedirectURL,
[
['context', 'data', 'token'],
['context', 'data', 'loginState', 'redirectUrl'],
],
'redirectUrl',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(redirectTo, [
['context', 'response'],
['context', 'data', 'redirectUrl'],
]),
),
),
lift(
withLogging(
orThrow([
[AuthenticationInvalidInputError, 400],
[AuthenticationNotFoundError, 404],
[AuthenticationUnexpectedDBError, 500],
[AuthenticationOAuthError, 500],
]),
),
),
),
method: 'GET',
path: '/auth/oauth/line/callback',
validators: [],
});

twitterOAuthRoute

Implementation

Endpoint: GET /auth/oauth/twitter

Access: Public; validators: [].

Request: twitterOauthSchema validates purpose, redirectUrl, optional typeId, and an optional empty JSON object.

Pipeline: prepareTwitterCallbackStaterequestTwitterOAuthorThrow.

Success: The injected twitterOAuthDriver.request handles the provider redirect.

Failure: orThrow([]) has no explicit source error mapping.

View complete source
export const twitterOAuthRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
prepareTwitterCallbackState,
[
['params', 'requestQuery', 'purpose'],
['params', 'requestQuery', 'redirectUrl'],
['params', 'requestQuery', 'typeId'],
],
'state',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(requestTwitterOAuth, [
['context', 'twitterOAuthDriver', 'request'],
['context', 'request'],
['context', 'response'],
['context', 'data', 'state'],
]),
),
),
lift(withLogging(orThrow([]))),
),
method: 'GET',
path: '/auth/oauth/twitter',
validators: [],
});

twitterOAuthCallbackRoute

Implementation

Endpoint: GET /auth/oauth/twitter/callback

Access: Public; validators: [].

Request: No composed schema; Twitter's driver supplies callback state.

Pipeline: authenticateTwitterOAuthverifyTwitterOAuthgetLoginTokenTargetgetFingerprintbuildTokenVerificationgenerateOneTimeTokenstoreOneTimeTokengenerateRedirectURLredirectToorThrow.

Success: 302 redirect with the generated onetimeToken.

Failure: Input 400, missing identity 404, database/OAuth failure 500.

View complete source
export const twitterOAuthCallbackRoute = withRoute({
handler: compose(
withLogging(
applyPayloadArgs(
authenticateTwitterOAuth,
[
['context', 'twitterOAuthDriver', 'callback'],
['context', 'request'],
['context', 'response'],
],
'callbackResult',
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
verifyTwitterOAuth,
[
['context', 'db', 'identities'],
['context', 'data', 'callbackResult', 'state', 'purpose'],
['context', 'data', 'callbackResult', 'state', 'typeId'],
['context', 'data', 'callbackResult', 'user'],
],
'identityId',
),
),
),
flatMapAsync(applyPayloadArgs(getLoginTokenTarget, [], 'target')),
flatMapAsync(withLogging(applyPayloadArgs(getFingerprint, [['context', 'request', 'headers']], 'fingerprint'))),
flatMapAsync(
withLogging(
applyPayloadArgs(
buildTokenVerification,
[
['context', 'request'],
['context', 'data', 'target'],
['context', 'data', 'fingerprint'],
],
'tokenVerification',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateOneTimeToken,
[
['context', 'configuration', 'authSecrets'],
['context', 'configuration', 'onetimeTokenSignOptions'],
['context', 'data', 'tokenVerification'],
['context', 'data', 'identityId'],
],
'token',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
storeOneTimeToken,
[
['context', 'db', 'onetimetokens'],
['context', 'data', 'token'],
],
'isStoredOneTimeToken',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(
generateRedirectURL,
[
['context', 'data', 'token'],
['context', 'data', 'callbackResult', 'state', 'redirectUrl'],
],
'redirectUrl',
),
),
),
flatMapAsync(
withLogging(
applyPayloadArgs(redirectTo, [
['context', 'response'],
['context', 'data', 'redirectUrl'],
]),
),
),
lift(
withLogging(
orThrow([
[AuthenticationInvalidInputError, 400],
[AuthenticationNotFoundError, 404],
[AuthenticationUnexpectedDBError, 500],
[AuthenticationOAuthError, 500],
]),
),
),
),
method: 'GET',
path: '/auth/oauth/twitter/callback',
validators: [],
});