Skip to content

Commit

Permalink
Added token exchange for native social endpoint [SDK-1307] (#273)
Browse files Browse the repository at this point in the history
* Add code exchange for native social endpoint
  • Loading branch information
Widcket authored Feb 6, 2020
1 parent 61f2b0e commit 9f7fc24
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/auth/__tests__/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,60 @@ Array [
]
`;

exports[`auth code exchange for native social should handle oauth error 1`] = `[invalid_request: Invalid grant]`;

exports[`auth code exchange for native social should handle unexpected error 1`] = `[a0.response.invalid: Internal Server Error]`;

exports[`auth code exchange for native social should return successful response 1`] = `
Object {
"accessToken": "an access token",
"expiresIn": 1234567890,
"idToken": "an id token",
"scope": "openid",
"state": "a random state for auth",
}
`;

exports[`auth code exchange for native social should return successful response with optional parameters 1`] = `
Object {
"accessToken": "an access token",
"expiresIn": 1234567890,
"idToken": "an id token",
"scope": "openid",
"state": "a random state for auth",
}
`;

exports[`auth code exchange for native social should send correct payload 1`] = `
Array [
"https://samples.auth0.com/oauth/token",
Object {
"body": "{\\"subject_token\\":\\"a subject token\\",\\"subject_token_type\\":\\"a subject token type\\",\\"client_id\\":\\"A_CLIENT_ID_OF_YOUR_ACCOUNT\\",\\"grant_type\\":\\"urn:ietf:params:oauth:grant-type:token-exchange\\"}",
"headers": Object {
"Accept": "application/json",
"Auth0-Client": "eyJuYW1lIjoicmVhY3QtbmF0aXZlLWF1dGgwIiwidmVyc2lvbiI6IjEuMC4wIn0=",
"Content-Type": "application/json",
},
"method": "POST",
},
]
`;

exports[`auth code exchange for native social should send correct payload with optional parameters 1`] = `
Array [
"https://samples.auth0.com/oauth/token",
Object {
"body": "{\\"subject_token\\":\\"a subject token\\",\\"subject_token_type\\":\\"a subject token type\\",\\"user_profile\\":{\\"name\\":{\\"firstName\\":\\"John\\",\\"lastName\\":\\"Smith\\"}},\\"audience\\":\\"http://myapi.com\\",\\"scope\\":\\"openid\\",\\"client_id\\":\\"A_CLIENT_ID_OF_YOUR_ACCOUNT\\",\\"grant_type\\":\\"urn:ietf:params:oauth:grant-type:token-exchange\\"}",
"headers": Object {
"Accept": "application/json",
"Auth0-Client": "eyJuYW1lIjoicmVhY3QtbmF0aXZlLWF1dGgwIiwidmVyc2lvbiI6IjEuMC4wIn0=",
"Content-Type": "application/json",
},
"method": "POST",
},
]
`;

exports[`auth code exchange should handle oauth error 1`] = `[invalid_request: Invalid grant]`;

exports[`auth code exchange should handle unexpected error 1`] = `[a0.response.invalid: Internal Server Error]`;
Expand Down
89 changes: 89 additions & 0 deletions src/auth/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,95 @@ describe('auth', () => {
});
});

describe('code exchange for native social', () => {
it('should send correct payload', async () => {
fetchMock.postOnce('https://samples.auth0.com/oauth/token', tokens);
expect.assertions(1);
await auth.exchangeNativeSocial({
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
});
expect(fetchMock.lastCall()).toMatchSnapshot();
});

it('should send correct payload with optional parameters', async () => {
fetchMock.postOnce('https://samples.auth0.com/oauth/token', tokens);
expect.assertions(1);
await auth.exchangeNativeSocial({
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
userProfile: {
name: {
firstName: 'John',
lastName: 'Smith',
},
},
audience: 'http://myapi.com',
scope: 'openid',
});
expect(fetchMock.lastCall()).toMatchSnapshot();
});

it('should return successful response', async () => {
fetchMock.postOnce('https://samples.auth0.com/oauth/token', tokens);
expect.assertions(1);
const parameters = {
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
};
await expect(
auth.exchangeNativeSocial(parameters),
).resolves.toMatchSnapshot();
});

it('should return successful response with optional parameters', async () => {
fetchMock.postOnce('https://samples.auth0.com/oauth/token', tokens);
expect.assertions(1);
const parameters = {
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
userProfile: {
name: {
firstName: 'John',
lastName: 'Smith',
},
},
audience: 'http://myapi.com',
scope: 'openid',
};
await expect(
auth.exchangeNativeSocial(parameters),
).resolves.toMatchSnapshot();
});

it('should handle oauth error', async () => {
fetchMock.postOnce('https://samples.auth0.com/oauth/token', oauthError);
expect.assertions(1);
const parameters = {
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
};
await expect(
auth.exchangeNativeSocial(parameters),
).rejects.toMatchSnapshot();
});

it('should handle unexpected error', async () => {
fetchMock.postOnce(
'https://samples.auth0.com/oauth/token',
unexpectedError,
);
expect.assertions(1);
const parameters = {
subjectToken: 'a subject token',
subjectTokenType: 'a subject token type',
};
await expect(
auth.exchangeNativeSocial(parameters),
).rejects.toMatchSnapshot();
});
});

describe('passwordless flow', () => {
describe('with email connection', () => {
it('should begin with code', async () => {
Expand Down
37 changes: 37 additions & 0 deletions src/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,43 @@ export default class Auth {
.then(responseHandler);
}

/**
* Exchanges an external token obtained via a native social authentication solution for the user's tokens
*
* @param {Object} parameters parameters used to obtain user tokens from an external provider's token
* @param {String} parameters.subjectToken token returned by the native social authentication solution
* @param {String} parameters.subjectTokenType identifier that indicates the native social authentication solution
* @param {Object} [parameters.userProfile] additional profile attributes to set or override, only on select native social authentication solutions
* @param {String} [parameters.audience] API audience to request
* @param {String} [parameters.scope] scopes requested for the issued tokens. e.g. `openid profile`
* @returns {Promise}
*
* @see https://auth0.com/docs/api/authentication#token-exchange-for-native-social
*
* @memberof Auth
*/
exchangeNativeSocial(parameters = {}) {
const payload = apply(
{
parameters: {
subjectToken: {required: true, toName: 'subject_token'},
subjectTokenType: {required: true, toName: 'subject_token_type'},
userProfile: {required: false, toName: 'user_profile'},
audience: {required: false},
scope: {required: false},
},
},
parameters,
);
return this.client
.post('/oauth/token', {
...payload,
client_id: this.clientId,
grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
})
.then(responseHandler);
}

/**
* Performs Auth with user credentials using the Password Realm Grant
*
Expand Down

0 comments on commit 9f7fc24

Please sign in to comment.