mirror of
https://github.com/logto-io/logto.git
synced 2025-02-17 22:04:19 -05:00
refactor(core): refactor createSocialAuthorizationUrl and verifySocialIdentity (#2707)
Co-authored-by: simeng-li <simeng@silverhand.io>
This commit is contained in:
parent
1b709db854
commit
8c5ccac59f
5 changed files with 37 additions and 34 deletions
|
@ -1,4 +1,3 @@
|
|||
import type { ConnectorSession } from '@logto/connector-kit';
|
||||
import type { LogtoErrorCode } from '@logto/phrases';
|
||||
import { Event, eventGuard, identifierPayloadGuard, profileGuard } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
|
@ -15,7 +14,6 @@ import type { AnonymousRouter } from '../types.js';
|
|||
import submitInteraction from './actions/submit-interaction.js';
|
||||
import { sendPasscodePayloadGuard, socialAuthorizationUrlPayloadGuard } from './types/guard.js';
|
||||
import {
|
||||
assignConnectorSessionResult,
|
||||
getInteractionStorage,
|
||||
storeInteractionResult,
|
||||
mergeIdentifiers,
|
||||
|
@ -236,11 +234,9 @@ export default function interactionRoutes<T extends AnonymousRouter>(
|
|||
// Check interaction exists
|
||||
await getInteractionStorage(ctx, provider);
|
||||
|
||||
const redirectTo = await createSocialAuthorizationUrl(
|
||||
ctx.guard.body,
|
||||
async (connectorStorage: ConnectorSession) =>
|
||||
assignConnectorSessionResult(ctx, provider, connectorStorage)
|
||||
);
|
||||
const { body: payload } = ctx.guard;
|
||||
|
||||
const redirectTo = await createSocialAuthorizationUrl(ctx, provider, payload);
|
||||
|
||||
ctx.body = { redirectTo };
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { ConnectorType } from '@logto/connector-kit';
|
||||
import { mockEsm } from '@logto/shared/esm';
|
||||
|
||||
import createMockContext from '#src/test-utils/jest-koa-mocks/create-mock-context.js';
|
||||
import { createMockLogContext } from '#src/test-utils/koa-audit-log.js';
|
||||
import { createMockProvider } from '#src/test-utils/oidc-provider.js';
|
||||
|
||||
const { jest } = import.meta;
|
||||
|
||||
|
@ -24,16 +26,13 @@ const log = createMockLogContext();
|
|||
|
||||
describe('social-verification', () => {
|
||||
it('verifySocialIdentity', async () => {
|
||||
const getSession = jest.fn();
|
||||
const provider = createMockProvider();
|
||||
const ctx = { ...createMockContext(), ...log };
|
||||
const connectorId = 'connector';
|
||||
const connectorData = { authCode: 'code' };
|
||||
const userInfo = await verifySocialIdentity(
|
||||
{ connectorId, connectorData },
|
||||
log.createLog,
|
||||
getSession
|
||||
);
|
||||
const userInfo = await verifySocialIdentity({ connectorId, connectorData }, ctx, provider);
|
||||
|
||||
expect(getUserInfoByAuthCode).toBeCalledWith(connectorId, connectorData, getSession);
|
||||
expect(getUserInfoByAuthCode).toBeCalledWith(connectorId, connectorData, expect.anything());
|
||||
expect(userInfo).toEqual({ id: 'foo' });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
import type { GetSession, SetSession } from '@logto/connector-kit';
|
||||
import type { ConnectorSession } from '@logto/connector-kit';
|
||||
import type { SocialConnectorPayload } from '@logto/schemas';
|
||||
import { ConnectorType } from '@logto/schemas';
|
||||
import type { Context } from 'koa';
|
||||
import type { Provider } from 'oidc-provider';
|
||||
|
||||
import { getLogtoConnectorById } from '#src/connectors/index.js';
|
||||
import type { SocialUserInfo } from '#src/connectors/types.js';
|
||||
import { getUserInfoByAuthCode } from '#src/libraries/social.js';
|
||||
import type { LogContext } from '#src/middleware/koa-audit-log.js';
|
||||
import {
|
||||
getConnectorSessionResult,
|
||||
assignConnectorSessionResult,
|
||||
} from '#src/routes/interaction/utils/interaction.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
|
||||
import type { SocialAuthorizationUrlPayload } from '../types/index.js';
|
||||
|
||||
export const createSocialAuthorizationUrl = async (
|
||||
payload: SocialAuthorizationUrlPayload,
|
||||
setConnectorSession?: SetSession
|
||||
ctx: Context,
|
||||
provider: Provider,
|
||||
payload: SocialAuthorizationUrlPayload
|
||||
) => {
|
||||
const { connectorId, state, redirectUri } = payload;
|
||||
assertThat(state && redirectUri, 'session.insufficient_info');
|
||||
|
@ -21,18 +28,26 @@ export const createSocialAuthorizationUrl = async (
|
|||
|
||||
assertThat(connector.type === ConnectorType.Social, 'connector.unexpected_type');
|
||||
|
||||
return connector.getAuthorizationUri({ state, redirectUri }, setConnectorSession);
|
||||
return connector.getAuthorizationUri(
|
||||
{ state, redirectUri },
|
||||
async (connectorStorage: ConnectorSession) =>
|
||||
assignConnectorSessionResult(ctx, provider, connectorStorage)
|
||||
);
|
||||
};
|
||||
|
||||
export const verifySocialIdentity = async (
|
||||
{ connectorId, connectorData }: SocialConnectorPayload,
|
||||
createLog: LogContext['createLog'],
|
||||
getSession?: GetSession
|
||||
ctx: Context,
|
||||
provider: Provider
|
||||
): Promise<SocialUserInfo> => {
|
||||
// eslint-disable-next-line prefer-destructuring, @typescript-eslint/no-unsafe-assignment
|
||||
const createLog: LogContext['createLog'] = ctx.createLog;
|
||||
const log = createLog('Interaction.SignIn.Identifier.Social.Submit');
|
||||
log.append({ connectorId, connectorData });
|
||||
|
||||
const userInfo = await getUserInfoByAuthCode(connectorId, connectorData, getSession);
|
||||
const userInfo = await getUserInfoByAuthCode(connectorId, connectorData, async () =>
|
||||
getConnectorSessionResult(ctx, provider)
|
||||
);
|
||||
|
||||
log.append(userInfo);
|
||||
|
||||
|
|
|
@ -154,18 +154,15 @@ describe('identifier verification', () => {
|
|||
it('social', async () => {
|
||||
const identifier = { connectorId: 'logto', connectorData: {} };
|
||||
|
||||
const provider = createMockProvider();
|
||||
const result = await identifierPayloadVerification(
|
||||
baseCtx,
|
||||
createMockProvider(),
|
||||
provider,
|
||||
identifier,
|
||||
interactionStorage
|
||||
);
|
||||
|
||||
expect(verifySocialIdentity).toBeCalledWith(
|
||||
identifier,
|
||||
logContext.createLog,
|
||||
expect.anything()
|
||||
);
|
||||
expect(verifySocialIdentity).toBeCalledWith(identifier, baseCtx, provider);
|
||||
expect(findUserByIdentifier).not.toBeCalled();
|
||||
|
||||
expect(result).toEqual({
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { GetSession } from '@logto/connector-kit';
|
||||
import type {
|
||||
Event,
|
||||
IdentifierPayload,
|
||||
|
@ -10,7 +9,6 @@ import type { Provider } from 'oidc-provider';
|
|||
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { verifyUserPassword } from '#src/libraries/user.js';
|
||||
import { getConnectorSessionResult } from '#src/routes/interaction/utils/interaction.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
|
||||
import type {
|
||||
|
@ -60,9 +58,9 @@ const verifyPasscodeIdentifier = async (
|
|||
const verifySocialIdentifier = async (
|
||||
identifier: SocialConnectorPayload,
|
||||
ctx: Context,
|
||||
getSession?: GetSession
|
||||
provider: Provider
|
||||
): Promise<SocialIdentifier> => {
|
||||
const userInfo = await verifySocialIdentity(identifier, ctx.createLog, getSession);
|
||||
const userInfo = await verifySocialIdentity(identifier, ctx, provider);
|
||||
|
||||
return { key: 'social', connectorId: identifier.connectorId, userInfo };
|
||||
};
|
||||
|
@ -104,9 +102,7 @@ export default async function identifierPayloadVerification(
|
|||
}
|
||||
|
||||
if (isSocialIdentifier(identifierPayload)) {
|
||||
return verifySocialIdentifier(identifierPayload, ctx, async () =>
|
||||
getConnectorSessionResult(ctx, provider)
|
||||
);
|
||||
return verifySocialIdentifier(identifierPayload, ctx, provider);
|
||||
}
|
||||
|
||||
// Sign-In with social verified email or phone
|
||||
|
|
Loading…
Add table
Reference in a new issue