feat: Improve authentication adapter interface to support multi-factor authentication (MFA), authentication challenges, and provide a more powerful interface for writing custom authentication adapters (#8156)
This commit is contained in:
@@ -942,8 +942,7 @@ describe('ParseGraphQLServer', () => {
|
||||
).data['__type'].inputFields
|
||||
.map(field => field.name)
|
||||
.sort();
|
||||
|
||||
expect(inputFields).toEqual(['clientMutationId', 'password', 'username']);
|
||||
expect(inputFields).toEqual(['authData', 'clientMutationId', 'password', 'username']);
|
||||
});
|
||||
|
||||
it('should have clientMutationId in log in mutation payload', async () => {
|
||||
@@ -7027,7 +7026,61 @@ describe('ParseGraphQLServer', () => {
|
||||
});
|
||||
|
||||
describe('Users Mutations', () => {
|
||||
const challengeAdapter = {
|
||||
validateAuthData: () => Promise.resolve({ response: { someData: true } }),
|
||||
validateAppId: () => Promise.resolve(),
|
||||
challenge: () => Promise.resolve({ someData: true }),
|
||||
options: { anOption: true },
|
||||
};
|
||||
|
||||
it('should create user and return authData response', async () => {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
auth: {
|
||||
challengeAdapter,
|
||||
},
|
||||
});
|
||||
const clientMutationId = uuidv4();
|
||||
|
||||
const result = await apolloClient.mutate({
|
||||
mutation: gql`
|
||||
mutation createUser($input: CreateUserInput!) {
|
||||
createUser(input: $input) {
|
||||
clientMutationId
|
||||
user {
|
||||
id
|
||||
authDataResponse
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
input: {
|
||||
clientMutationId,
|
||||
fields: {
|
||||
authData: {
|
||||
challengeAdapter: {
|
||||
id: 'challengeAdapter',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.data.createUser.clientMutationId).toEqual(clientMutationId);
|
||||
expect(result.data.createUser.user.authDataResponse).toEqual({
|
||||
challengeAdapter: { someData: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('should sign user up', async () => {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
auth: {
|
||||
challengeAdapter,
|
||||
},
|
||||
});
|
||||
const clientMutationId = uuidv4();
|
||||
const userSchema = new Parse.Schema('_User');
|
||||
userSchema.addString('someField');
|
||||
@@ -7044,6 +7097,7 @@ describe('ParseGraphQLServer', () => {
|
||||
sessionToken
|
||||
user {
|
||||
someField
|
||||
authDataResponse
|
||||
aPointer {
|
||||
id
|
||||
username
|
||||
@@ -7059,6 +7113,11 @@ describe('ParseGraphQLServer', () => {
|
||||
fields: {
|
||||
username: 'user1',
|
||||
password: 'user1',
|
||||
authData: {
|
||||
challengeAdapter: {
|
||||
id: 'challengeAdapter',
|
||||
},
|
||||
},
|
||||
aPointer: {
|
||||
createAndLink: {
|
||||
username: 'user2',
|
||||
@@ -7078,6 +7137,9 @@ describe('ParseGraphQLServer', () => {
|
||||
expect(result.data.signUp.viewer.user.aPointer.id).toBeDefined();
|
||||
expect(result.data.signUp.viewer.user.aPointer.username).toEqual('user2');
|
||||
expect(typeof result.data.signUp.viewer.sessionToken).toBe('string');
|
||||
expect(result.data.signUp.viewer.user.authDataResponse).toEqual({
|
||||
challengeAdapter: { someData: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('should login with user', async () => {
|
||||
@@ -7086,6 +7148,7 @@ describe('ParseGraphQLServer', () => {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
auth: {
|
||||
challengeAdapter,
|
||||
myAuth: {
|
||||
module: global.mockCustomAuthenticator('parse', 'graphql'),
|
||||
},
|
||||
@@ -7105,6 +7168,7 @@ describe('ParseGraphQLServer', () => {
|
||||
sessionToken
|
||||
user {
|
||||
someField
|
||||
authDataResponse
|
||||
aPointer {
|
||||
id
|
||||
username
|
||||
@@ -7118,6 +7182,7 @@ describe('ParseGraphQLServer', () => {
|
||||
input: {
|
||||
clientMutationId,
|
||||
authData: {
|
||||
challengeAdapter: { id: 'challengeAdapter' },
|
||||
myAuth: {
|
||||
id: 'parse',
|
||||
password: 'graphql',
|
||||
@@ -7143,9 +7208,92 @@ describe('ParseGraphQLServer', () => {
|
||||
expect(typeof result.data.logInWith.viewer.sessionToken).toBe('string');
|
||||
expect(result.data.logInWith.viewer.user.aPointer.id).toBeDefined();
|
||||
expect(result.data.logInWith.viewer.user.aPointer.username).toEqual('user2');
|
||||
expect(result.data.logInWith.viewer.user.authDataResponse).toEqual({
|
||||
challengeAdapter: { someData: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle challenge', async () => {
|
||||
const clientMutationId = uuidv4();
|
||||
|
||||
spyOn(challengeAdapter, 'challenge').and.callThrough();
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
auth: {
|
||||
challengeAdapter,
|
||||
},
|
||||
});
|
||||
|
||||
const user = new Parse.User();
|
||||
await user.save({ username: 'username', password: 'password' });
|
||||
|
||||
const result = await apolloClient.mutate({
|
||||
mutation: gql`
|
||||
mutation Challenge($input: ChallengeInput!) {
|
||||
challenge(input: $input) {
|
||||
clientMutationId
|
||||
challengeData
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
input: {
|
||||
clientMutationId,
|
||||
username: 'username',
|
||||
password: 'password',
|
||||
challengeData: {
|
||||
challengeAdapter: { someChallengeData: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const challengeCall = challengeAdapter.challenge.calls.argsFor(0);
|
||||
expect(challengeAdapter.challenge).toHaveBeenCalledTimes(1);
|
||||
expect(challengeCall[0]).toEqual({ someChallengeData: true });
|
||||
expect(challengeCall[1]).toEqual(undefined);
|
||||
expect(challengeCall[2]).toEqual(challengeAdapter);
|
||||
expect(challengeCall[3].object instanceof Parse.User).toBeTruthy();
|
||||
expect(challengeCall[3].original instanceof Parse.User).toBeTruthy();
|
||||
expect(challengeCall[3].isChallenge).toBeTruthy();
|
||||
expect(challengeCall[3].object.id).toEqual(user.id);
|
||||
expect(challengeCall[3].original.id).toEqual(user.id);
|
||||
expect(result.data.challenge.clientMutationId).toEqual(clientMutationId);
|
||||
expect(result.data.challenge.challengeData).toEqual({
|
||||
challengeAdapter: { someData: true },
|
||||
});
|
||||
|
||||
await expectAsync(
|
||||
apolloClient.mutate({
|
||||
mutation: gql`
|
||||
mutation Challenge($input: ChallengeInput!) {
|
||||
challenge(input: $input) {
|
||||
clientMutationId
|
||||
challengeData
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
input: {
|
||||
clientMutationId,
|
||||
username: 'username',
|
||||
password: 'wrongPassword',
|
||||
challengeData: {
|
||||
challengeAdapter: { someChallengeData: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
).toBeRejected();
|
||||
});
|
||||
|
||||
it('should log the user in', async () => {
|
||||
parseServer = await global.reconfigureServer({
|
||||
publicServerURL: 'http://localhost:13377/parse',
|
||||
auth: {
|
||||
challengeAdapter,
|
||||
},
|
||||
});
|
||||
const clientMutationId = uuidv4();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user1');
|
||||
@@ -7162,6 +7310,7 @@ describe('ParseGraphQLServer', () => {
|
||||
viewer {
|
||||
sessionToken
|
||||
user {
|
||||
authDataResponse
|
||||
someField
|
||||
}
|
||||
}
|
||||
@@ -7173,6 +7322,7 @@ describe('ParseGraphQLServer', () => {
|
||||
clientMutationId,
|
||||
username: 'user1',
|
||||
password: 'user1',
|
||||
authData: { challengeAdapter: { token: true } },
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -7181,6 +7331,9 @@ describe('ParseGraphQLServer', () => {
|
||||
expect(result.data.logIn.viewer.sessionToken).toBeDefined();
|
||||
expect(result.data.logIn.viewer.user.someField).toEqual('someValue');
|
||||
expect(typeof result.data.logIn.viewer.sessionToken).toBe('string');
|
||||
expect(result.data.logIn.viewer.user.authDataResponse).toEqual({
|
||||
challengeAdapter: { someData: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('should log the user out', async () => {
|
||||
|
||||
Reference in New Issue
Block a user