-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sdk-middleware-auth): implement anonymous session flow
affects: @commercetools/sdk-middleware-auth resolves #276
- Loading branch information
1 parent
55a504c
commit 30a9f0b
Showing
11 changed files
with
343 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { createClient } from '@commercetools/sdk-client' | ||
import { getCredentials } from '@commercetools/get-credentials' | ||
import { | ||
createAuthMiddlewareForPasswordFlow, | ||
createAuthMiddlewareForAnonymousSessionFlow, | ||
} from '@commercetools/sdk-middleware-auth' | ||
import { | ||
createHttpMiddleware, | ||
} from '@commercetools/sdk-middleware-http' | ||
import { clearData, createData } from './../cli/helpers/utils' | ||
|
||
let projectKey | ||
if (process.env.CI === 'true') | ||
projectKey = 'auth-integration-test' | ||
else | ||
projectKey = process.env.npm_config_projectkey | ||
|
||
describe('Auth Flows', () => { | ||
let apiConfig | ||
const userEmail = `abi${Date.now()}@commercetooler.com` | ||
const userPassword = 'asdifficultaspossible' | ||
beforeAll(() => getCredentials(projectKey) | ||
.then((credentials) => { | ||
apiConfig = { | ||
host: 'https://auth.sphere.io', | ||
apiUrl: 'https://api.sphere.io', | ||
projectKey, | ||
credentials: { | ||
clientId: credentials.clientId, | ||
clientSecret: credentials.clientSecret, | ||
}, | ||
} | ||
}) | ||
.then(() => clearData(apiConfig, 'customers')) | ||
.then(() => clearData(apiConfig, 'carts')) | ||
.then(() => createData(apiConfig, 'customers', [{ | ||
email: userEmail, | ||
password: userPassword, | ||
}])) | ||
, 10000) | ||
afterAll(() => { | ||
clearData(apiConfig, 'customers') | ||
.then(() => clearData(apiConfig, 'carts')) | ||
}) | ||
describe('Password Session Flow', () => { | ||
const httpMiddleware = createHttpMiddleware({ | ||
host: 'https://api.sphere.io', | ||
}) | ||
|
||
it('should log customer and fetch customer profile', () => { | ||
const userConfig = { | ||
...apiConfig, | ||
...{ scopes: [ `manage_project:${projectKey}` ] }, | ||
...{ credentials: { | ||
clientId: apiConfig.credentials.clientId, | ||
clientSecret: apiConfig.credentials.clientSecret, | ||
user: { | ||
username: userEmail, | ||
password: userPassword, | ||
}, | ||
} }, | ||
} | ||
const client = createClient({ | ||
middlewares: [ | ||
createAuthMiddlewareForPasswordFlow(userConfig), | ||
httpMiddleware, | ||
], | ||
}) | ||
return client.execute({ | ||
uri: `/${projectKey}/me`, | ||
method: 'GET', | ||
}).then((response) => { | ||
const user = response.body | ||
expect(user).toHaveProperty('email', userEmail) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('Anonymous Session Flow', () => { | ||
const httpMiddleware = createHttpMiddleware({ | ||
host: 'https://api.sphere.io', | ||
}) | ||
|
||
it('create an anonymous session and a cart tied to the session', () => { | ||
const anonymousId = `${Date.now()}-bar` | ||
const userConfig = { | ||
...apiConfig, | ||
...{ scopes: [ `manage_project:${projectKey}` ] }, | ||
...{ credentials: { | ||
clientId: apiConfig.credentials.clientId, | ||
clientSecret: apiConfig.credentials.clientSecret, | ||
anonymousId, | ||
} }, | ||
} | ||
const client = createClient({ | ||
middlewares: [ | ||
createAuthMiddlewareForAnonymousSessionFlow(userConfig), | ||
httpMiddleware, | ||
], | ||
}) | ||
const cartMock = { | ||
currency: 'EUR', | ||
} | ||
return client.execute({ | ||
// creates a cart that is tied to the logged in anonymous token | ||
uri: `/${projectKey}/me/carts`, | ||
method: 'POST', | ||
body: cartMock, | ||
}).then(({ body: cart }) => { | ||
expect(cart).toHaveProperty('anonymousId', anonymousId) | ||
return client.execute({ | ||
// fetch all carts tied to the anonymous token, if cart is present, | ||
// then the cart was tied to the token | ||
uri: `/${projectKey}/me/carts`, | ||
method: 'GET', | ||
}) | ||
}).then(({ body: { results: carts } }) => { | ||
expect(carts).toHaveLength(1) | ||
expect(carts[0]).toHaveProperty('anonymousId', anonymousId) | ||
}) | ||
}, 7000) | ||
}) | ||
}) |
This file was deleted.
Oops, something went wrong.
37 changes: 35 additions & 2 deletions
37
packages/sdk-middleware-auth/src/anonymous-session-flow.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,36 @@ | ||
export default function createAuthMiddlewareForAnonymousSessionFlow () { | ||
throw new Error('Middleware not implemented yet') | ||
/* @flow */ | ||
import type { | ||
AuthMiddlewareOptions, | ||
Middleware, | ||
MiddlewareRequest, | ||
MiddlewareResponse, | ||
Next, | ||
Task, | ||
} from 'types/sdk' | ||
|
||
import { buildRequestForAnonymousSessionFlow } from './build-requests' | ||
import authMiddlewareBase from './base-auth-flow' | ||
import store from './utils' | ||
|
||
export default function createAuthMiddlewareForAnonymousSessionFlow ( | ||
options: AuthMiddlewareOptions, | ||
): Middleware { | ||
const tokenCache = store({}) | ||
const pendingTasks: Array<Task> = [] | ||
|
||
const requestState = store(false) | ||
return (next: Next) => ( | ||
request: MiddlewareRequest, | ||
response: MiddlewareResponse, | ||
) => { | ||
const params = { | ||
request, | ||
response, | ||
...buildRequestForAnonymousSessionFlow(options), | ||
pendingTasks, | ||
requestState, | ||
tokenCache, | ||
} | ||
authMiddlewareBase(params, next) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
30a9f0b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed that this commit is a breaking change, but it was not released like that
It's a breaking change because the parameters are now required, whereas before if you pass an authorization header, it's going to skip the parameter validation check.
@wizzy25 how best do you think we handle this
30a9f0b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hisabimbola we can roll it back; skip the validation if authorization header is passed in