Skip to content

Commit

Permalink
feat: Improve authentication adapter interface to support multi-facto…
Browse files Browse the repository at this point in the history
…r authentication (MFA), authentication challenges, and provide a more powerful interface for writing custom authentication adapters (parse-community#8156)
  • Loading branch information
dblythy committed Nov 10, 2022
1 parent 4eb5f28 commit 5bbf9ca
Show file tree
Hide file tree
Showing 20 changed files with 2,394 additions and 267 deletions.
1 change: 1 addition & 0 deletions DEPRECATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
| DEPPS5 | Config option `allowClientClassCreation` defaults to `false` | [#7925](https://github.com/parse-community/parse-server/pull/7925) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |

[i_deprecation]: ## "The version and date of the deprecation."
[i_removal]: ## "The version and date of the planned removal."
Expand Down
73 changes: 62 additions & 11 deletions spec/AuthenticationAdapters.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,49 @@ describe('AuthenticationProviders', function () {
.catch(done.fail);
});

it('should support loginWith with session token and with/without mutated authData', async () => {
const fakeAuthProvider = {
validateAppId: () => Promise.resolve(),
validateAuthData: () => Promise.resolve(),
};
const payload = { authData: { id: 'user1', token: 'fakeToken' } };
const payload2 = { authData: { id: 'user1', token: 'fakeToken2' } };
await reconfigureServer({ auth: { fakeAuthProvider } });
const user = await Parse.User.logInWith('fakeAuthProvider', payload);
const user2 = await Parse.User.logInWith('fakeAuthProvider', payload, {
sessionToken: user.getSessionToken(),
});
const user3 = await Parse.User.logInWith('fakeAuthProvider', payload2, {
sessionToken: user2.getSessionToken(),
});
expect(user.id).toEqual(user2.id);
expect(user.id).toEqual(user3.id);
});

it('should support sync/async validateAppId', async () => {
const syncProvider = {
validateAppId: () => true,
appIds: 'test',
validateAuthData: () => Promise.resolve(),
};
const asyncProvider = {
appIds: 'test',
validateAppId: () => Promise.resolve(true),
validateAuthData: () => Promise.resolve(),
};
const payload = { authData: { id: 'user1', token: 'fakeToken' } };
const syncSpy = spyOn(syncProvider, 'validateAppId');
const asyncSpy = spyOn(asyncProvider, 'validateAppId');

await reconfigureServer({ auth: { asyncProvider, syncProvider } });
const user = await Parse.User.logInWith('asyncProvider', payload);
const user2 = await Parse.User.logInWith('syncProvider', payload);
expect(user.getSessionToken()).toBeDefined();
expect(user2.getSessionToken()).toBeDefined();
expect(syncSpy).toHaveBeenCalledTimes(1);
expect(asyncSpy).toHaveBeenCalledTimes(1);
});

it('unlink and link with custom provider', async () => {
const provider = getMockMyOauthProvider();
Parse.User._registerAuthenticationProvider(provider);
Expand Down Expand Up @@ -339,10 +382,10 @@ describe('AuthenticationProviders', function () {
});

validateAuthenticationHandler(authenticationHandler);
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
const { validator } = authenticationHandler.getValidatorForProvider('customAuthentication');
validateValidator(validator);

validator(validAuthData).then(
validator(validAuthData, {}, {}).then(
() => {
expect(authDataSpy).toHaveBeenCalled();
// AppIds are not provided in the adapter, should not be called
Expand All @@ -362,12 +405,15 @@ describe('AuthenticationProviders', function () {
});

validateAuthenticationHandler(authenticationHandler);
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
const { validator } = authenticationHandler.getValidatorForProvider('customAuthentication');
validateValidator(validator);

validator({
token: 'my-token',
}).then(
validator(
{
token: 'my-token',
},
{},
{}
).then(
() => {
done();
},
Expand All @@ -387,12 +433,16 @@ describe('AuthenticationProviders', function () {
});

validateAuthenticationHandler(authenticationHandler);
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
const { validator } = authenticationHandler.getValidatorForProvider('customAuthentication');
validateValidator(validator);

validator({
token: 'valid-token',
}).then(
validator(
{
token: 'valid-token',
},
{},
{}
).then(
() => {
done();
},
Expand Down Expand Up @@ -541,6 +591,7 @@ describe('AuthenticationProviders', function () {
});

it('can depreciate', async () => {
await reconfigureServer();
const Deprecator = require('../lib/Deprecator/Deprecator');
const spy = spyOn(Deprecator, 'logRuntimeDeprecation').and.callFake(() => {});
const provider = getMockMyOauthProvider();
Expand Down

0 comments on commit 5bbf9ca

Please sign in to comment.