From c41ecc77046b50e865b643f5ce9aa8238e3297d9 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Mon, 14 Aug 2017 18:02:44 +0200
Subject: [PATCH 01/21] feat(password-flow): add method to build valid password
 auth uri

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/src/build-requests.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/src/build-requests.js b/packages/sdk-middleware-auth/src/build-requests.js
index b95f03152..8bf6bab95 100644
--- a/packages/sdk-middleware-auth/src/build-requests.js
+++ b/packages/sdk-middleware-auth/src/build-requests.js
@@ -78,7 +78,6 @@ export function buildRequestForPasswordFlow (
   const scope = (options.scopes || []).join(' ')
   const scopeStr = scope ? `&scope=${scope}` : ''
 
-
   const basicAuth = new Buffer(`${clientId}:${clientSecret}`).toString('base64')
   // This is mostly useful for internal testing purposes to be able to check
   // other oauth endpoints.

From 5674403062becdc831b65112815d3252b0aa40d9 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Tue, 15 Aug 2017 11:58:11 +0200
Subject: [PATCH 02/21] feat(sdk-middleware-auth): implement password flow

affects: @commercetools/sdk-middleware-auth

ISSUES CLOSED: #212
---
 packages/sdk-middleware-auth/test/password-flow.spec.js | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/packages/sdk-middleware-auth/test/password-flow.spec.js b/packages/sdk-middleware-auth/test/password-flow.spec.js
index 0005003ab..a860cee6a 100644
--- a/packages/sdk-middleware-auth/test/password-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/password-flow.spec.js
@@ -4,8 +4,6 @@ import {
 
 import authMiddlewareBase from '../src/base-auth-flow'
 
-jest.mock('../src/base-auth-flow')
-
 function createTestRequest (options) {
   return {
     url: '',
@@ -33,6 +31,12 @@ function createTestMiddlewareOptions (options) {
 }
 
 describe('Password Flow', () => {
+  beforeAll(() => {
+    jest.mock('../src/base-auth-flow')
+  })
+  afterAll(() => {
+    jest.unmock('../src/base-auth-flow')
+  })
   it('should call the base-auth-flow method with the right params', () =>
     new Promise((resolve, reject) => {
       authMiddlewareBase.mockImplementation((params, next) => {
@@ -52,7 +56,6 @@ describe('Password Flow', () => {
           basicAuth: 'MTIzOnNlY3JldA==',
         })
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
-        jest.unmock('../src/base-auth-flow')
         resolve()
       }
       const middlewareOptions = createTestMiddlewareOptions()

From a9e5418d9deaddb556cb0df3fe1bfce92ad777fc Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Thu, 17 Aug 2017 12:27:11 +0200
Subject: [PATCH 03/21] refactor(base-auth-flow): refactor fetching token logic

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/src/base-auth-flow.js      | 1 -
 packages/sdk-middleware-auth/test/password-flow.spec.js | 9 ++++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/packages/sdk-middleware-auth/src/base-auth-flow.js b/packages/sdk-middleware-auth/src/base-auth-flow.js
index fc77cd65a..1b266fa75 100644
--- a/packages/sdk-middleware-auth/src/base-auth-flow.js
+++ b/packages/sdk-middleware-auth/src/base-auth-flow.js
@@ -9,7 +9,6 @@ import type {
 /* global fetch */
 import 'isomorphic-fetch'
 
-
 export default function authMiddlewareBase ({
     request,
     response,
diff --git a/packages/sdk-middleware-auth/test/password-flow.spec.js b/packages/sdk-middleware-auth/test/password-flow.spec.js
index a860cee6a..ee05f3321 100644
--- a/packages/sdk-middleware-auth/test/password-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/password-flow.spec.js
@@ -4,6 +4,11 @@ import {
 
 import authMiddlewareBase from '../src/base-auth-flow'
 
+// required to be at the root because Jest hoists it avoid all requires,
+// if in any method like `beforeAll`,
+// it will be hoisted within the scope of that method
+jest.mock('../src/base-auth-flow')
+
 function createTestRequest (options) {
   return {
     url: '',
@@ -30,10 +35,8 @@ function createTestMiddlewareOptions (options) {
   }
 }
 
+
 describe('Password Flow', () => {
-  beforeAll(() => {
-    jest.mock('../src/base-auth-flow')
-  })
   afterAll(() => {
     jest.unmock('../src/base-auth-flow')
   })

From 8049663218a417ab123fd650e8835fd6905ac267 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 11:27:33 +0200
Subject: [PATCH 04/21] test(base-auth-flow): add tests

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/test/base-auth-flow.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/test/base-auth-flow.spec.js b/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
index 8d86b8014..80cd0e05c 100644
--- a/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
@@ -185,7 +185,7 @@ describe('Base Auth Flow', () => {
       }
       // Second call:
       // - we simulate that the request has a token set in the headers
-      // - the previous token was expired though, so we need to refetch it
+      // - the previous token was expired though, so we need to refetch it.
       const call2 = () => {
         expect(requestCount).toBe(1)
         createBaseMiddleware({ requestState, tokenCache }, call3)

From 8282a59bf5bd6c3352de2ca0b29158ae1ddd9077 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 11:39:25 +0200
Subject: [PATCH 05/21] chore(base-auth-flow): add comments to tests

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/test/base-auth-flow.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/test/base-auth-flow.spec.js b/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
index 80cd0e05c..8d86b8014 100644
--- a/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/base-auth-flow.spec.js
@@ -185,7 +185,7 @@ describe('Base Auth Flow', () => {
       }
       // Second call:
       // - we simulate that the request has a token set in the headers
-      // - the previous token was expired though, so we need to refetch it.
+      // - the previous token was expired though, so we need to refetch it
       const call2 = () => {
         expect(requestCount).toBe(1)
         createBaseMiddleware({ requestState, tokenCache }, call3)

From 3b2d9f68714cf4bd6dabda2a55ea42ce766a97eb Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 12:05:46 +0200
Subject: [PATCH 06/21] docs(password-flow): add docs about new auth flow

---
 docs/sdk/api/sdkMiddlewareAuth.md | 36 +++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/docs/sdk/api/sdkMiddlewareAuth.md b/docs/sdk/api/sdkMiddlewareAuth.md
index c4b58313a..1fd4f40bb 100644
--- a/docs/sdk/api/sdkMiddlewareAuth.md
+++ b/docs/sdk/api/sdkMiddlewareAuth.md
@@ -89,3 +89,39 @@ const client = createClient({
   ],
 })
 ```
+
+## `createAuthMiddlewareForPasswordFlow(options)`
+
+Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for the [Password Flow](http://dev.commercetools.com/http-api-authorization.html#password-flow) of the commercetools platform API.
+
+#### Named arguments (options)
+
+1. `host` *(String)*: the host of the OAuth API service
+2. `projectKey` *(String)*: the key of the project to assign the default scope to
+3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret`)
+4. `scopes` *(Array)*: a list of [scopes](http://dev.commercetools.com/http-api-authorization.html#scopes) (default `manage_project:{projectKey}`) to assign to the OAuth token
+
+
+#### Usage example
+
+```js
+import { createClient } from '@commercetools/sdk-client'
+import { createAuthMiddlewareForPasswordFlow } from '@commercetools/sdk-middleware-auth'
+
+const client = createClient({
+  middlewares: [
+    createAuthMiddlewareForPasswordFlow({
+      host: 'https://auth.commercetools.com',
+      projectKey: 'test',
+      credentials: {
+        clientId: '123',
+        clientSecret: 'secret',
+      },
+      scopes: [
+        'view_products:test',
+        'manage_orders:test',
+      ],
+    }),
+  ],
+})
+```

From ac0cf358d66120583456b6dd5675e2a52c7c2bd4 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 12:10:04 +0200
Subject: [PATCH 07/21] docs(password-flow): update docs

---
 docs/sdk/api/sdkMiddlewareAuth.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/sdk/api/sdkMiddlewareAuth.md b/docs/sdk/api/sdkMiddlewareAuth.md
index 1fd4f40bb..ca25d595b 100644
--- a/docs/sdk/api/sdkMiddlewareAuth.md
+++ b/docs/sdk/api/sdkMiddlewareAuth.md
@@ -40,6 +40,10 @@ const client = createClient({
       credentials: {
         clientId: '123',
         clientSecret: 'secret',
+        user: {
+          username: string;
+          password: string;
+        }
       },
       scopes: [
         'view_products:test',

From a8ecfd24389fa69c6f3e872feba5e99d814c0e81 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 12:47:42 +0200
Subject: [PATCH 08/21] refactor(middleware-auth): remove duplicate tests

affects: @commercetools/sdk-middleware-auth
---
 .../sdk-middleware-auth/test/client-crendentials-flow.spec.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
index cf1f41c43..13c803364 100644
--- a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
@@ -28,6 +28,9 @@ function createTestMiddlewareOptions (options) {
 }
 
 describe('Client Crentials Flow', () => {
+  afterAll(() => {
+    jest.unmock('../src/base-auth-flow')
+  })
   it('should call the base-auth-flow method with the right params', () =>
     new Promise((resolve, reject) => {
       authMiddlewareBase.mockImplementation((params, next) => {
@@ -48,7 +51,6 @@ describe('Client Crentials Flow', () => {
         })
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
         resolve()
-        jest.unmock('../src/base-auth-flow')
       }
       const middlewareOptions = createTestMiddlewareOptions()
       const authMiddleware = createAuthMiddlewareForClientCredentialsFlow(

From 30d96daac034ea0c85df0e888babccc1be5b7b0e Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 14:02:53 +0200
Subject: [PATCH 09/21] refactor(middleware-auth): update base on PR review

affects: @commercetools/sdk-middleware-auth
---
 .../sdk-middleware-auth/test/client-crendentials-flow.spec.js    | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
index 13c803364..07180fe22 100644
--- a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
@@ -51,6 +51,7 @@ describe('Client Crentials Flow', () => {
         })
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
         resolve()
+        resolve()
       }
       const middlewareOptions = createTestMiddlewareOptions()
       const authMiddleware = createAuthMiddlewareForClientCredentialsFlow(

From 22c93b536cb99b8090e6cb3445c46ec9da06773d Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 15:54:20 +0200
Subject: [PATCH 10/21] refactor(middleware-auth): improve code

affects: @commercetools/sdk-middleware-auth
---
 .../sdk-middleware-auth/test/client-crendentials-flow.spec.js   | 2 +-
 packages/sdk-middleware-auth/test/password-flow.spec.js         | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
index 07180fe22..263013707 100644
--- a/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/client-crendentials-flow.spec.js
@@ -51,7 +51,7 @@ describe('Client Crentials Flow', () => {
         })
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
         resolve()
-        resolve()
+        jest.unmock('../src/base-auth-flow')
       }
       const middlewareOptions = createTestMiddlewareOptions()
       const authMiddleware = createAuthMiddlewareForClientCredentialsFlow(
diff --git a/packages/sdk-middleware-auth/test/password-flow.spec.js b/packages/sdk-middleware-auth/test/password-flow.spec.js
index ee05f3321..89dca8da8 100644
--- a/packages/sdk-middleware-auth/test/password-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/password-flow.spec.js
@@ -59,6 +59,7 @@ describe('Password Flow', () => {
           basicAuth: 'MTIzOnNlY3JldA==',
         })
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
+        jest.unmock('../src/base-auth-flow')
         resolve()
       }
       const middlewareOptions = createTestMiddlewareOptions()

From 186d927f459b717eff2843cb3c04618fa32c2f18 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Mon, 21 Aug 2017 13:04:12 +0200
Subject: [PATCH 11/21] test(integration): add integration tests for customer
 login

affects: @commercetools/sdk-middleware-auth
---
 integration-tests/sdk/customer-login.it.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/integration-tests/sdk/customer-login.it.js b/integration-tests/sdk/customer-login.it.js
index ab1a79456..da1095266 100644
--- a/integration-tests/sdk/customer-login.it.js
+++ b/integration-tests/sdk/customer-login.it.js
@@ -40,6 +40,7 @@ describe('Customer Login', () => {
     }])),
   )
   afterAll(() => clearData(apiConfig, 'customers'))
+
   it('should log customer and fetch customer profile', () => {
     const userConfig = {
       ...apiConfig,

From c2ce612f260514e3f95111f6ec10885e9ee62bf5 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Mon, 21 Aug 2017 13:14:24 +0200
Subject: [PATCH 12/21] refactor(auth): refactor code base on PR review

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/src/base-auth-flow.js | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/src/base-auth-flow.js b/packages/sdk-middleware-auth/src/base-auth-flow.js
index 1b266fa75..b243e4009 100644
--- a/packages/sdk-middleware-auth/src/base-auth-flow.js
+++ b/packages/sdk-middleware-auth/src/base-auth-flow.js
@@ -5,7 +5,6 @@ import type {
   Task,
   AuthMiddlewareBaseOptions,
 } from 'types/sdk'
-
 /* global fetch */
 import 'isomorphic-fetch'
 

From 655c6adf2fdd42bba80e554f3d95afade9aa5bba Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 16:02:27 +0200
Subject: [PATCH 13/21] feat(middleware-auth): add anonymous token
 implementation

affects: @commercetools/sdk-middleware-auth
---
 .../sdk-middleware-auth/src/build-requests.js | 14 +++++++--
 .../test/build-requests.spec.js               | 30 ++++++++++++++++++-
 types/sdk.js                                  |  2 ++
 3 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/packages/sdk-middleware-auth/src/build-requests.js b/packages/sdk-middleware-auth/src/build-requests.js
index 8bf6bab95..bebed7815 100644
--- a/packages/sdk-middleware-auth/src/build-requests.js
+++ b/packages/sdk-middleware-auth/src/build-requests.js
@@ -93,6 +93,16 @@ export function buildRequestForRefreshTokenFlow () {
   // TODO
 }
 
-export function buildRequestForAnonymousSessionFlow () {
-  // TODO
+export function buildRequestForAnonymousSessionFlow (
+  options: AuthMiddlewareOptions = {},
+): BuiltRequestParams {
+  const pKey = options.projectKey
+  // eslint-disable-next-line no-param-reassign
+  options.oauthUri = options.oauthUri || `/oauth/${pKey}/anonymous/token`
+  const result = buildRequestForClientCredentialsFlow(options)
+
+  if (options.credentials.anonymousId)
+    result.body += `&anonymous_id=${options.credentials.anonymousId}`
+
+  return { ...result }
 }
diff --git a/packages/sdk-middleware-auth/test/build-requests.spec.js b/packages/sdk-middleware-auth/test/build-requests.spec.js
index 46ef1d268..346510358 100644
--- a/packages/sdk-middleware-auth/test/build-requests.spec.js
+++ b/packages/sdk-middleware-auth/test/build-requests.spec.js
@@ -4,7 +4,7 @@ import {
   buildRequestForClientCredentialsFlow,
   buildRequestForPasswordFlow,
   // buildRequestForRefreshTokenFlow,
-  // buildRequestForAnonymousSessionFlow,
+  buildRequestForAnonymousSessionFlow,
 } from '../src/build-requests'
 import { scopes } from '../src'
 
@@ -231,3 +231,31 @@ describe('buildRequestForClientCredentialsFlow', () => {
     ).toThrowError('Missing required credentials (clientId, clientSecret)')
   })
 })
+
+describe('buildRequestForAnonymousSessionFlow', () => {
+  it('build request values with all the given options', () => {
+    const options = createTestOptions()
+    expect(buildRequestForAnonymousSessionFlow(options)).toEqual({
+      basicAuth: 'MTIzOnNlY3JldA==',
+      url: 'http://localhost:8080/oauth/test/anonymous/token',
+      body: `grant_type=client_credentials&scope=${allScopes.join(' ')}`,
+    })
+  })
+
+  it('should add anonymousId if passed in', () => {
+    const mockCred = {
+      clientId: '123',
+      clientSecret: 'secret',
+      anonymousId: 'youdontknowme',
+    }
+    const options = createTestOptions({ credentials: mockCred })
+    expect(buildRequestForAnonymousSessionFlow(options)).toEqual({
+      basicAuth: 'MTIzOnNlY3JldA==',
+      url: 'http://localhost:8080/oauth/test/anonymous/token',
+      body: oneLineTrim`grant_type=client_credentials&
+        scope=${allScopes.join(' ')}&
+        anonymous_id=youdontknowme
+      `,
+    })
+  })
+})
diff --git a/types/sdk.js b/types/sdk.js
index eb4e0ebef..0ec78f33e 100644
--- a/types/sdk.js
+++ b/types/sdk.js
@@ -66,12 +66,14 @@ export type Middleware = (next: Dispatch) => Dispatch;
 export type ClientOptions = {
   middlewares: Array<Middleware>;
 }
+
 export type AuthMiddlewareOptions = {
   host: string;
   projectKey: string;
   credentials: {
     clientId: string;
     clientSecret: string;
+    anonymousId?: string;
   };
   scopes: Array<string>;
   // For internal usage only

From ce81d264e16eabc942f5023053c8c382ede97179 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Fri, 18 Aug 2017 16:13:26 +0200
Subject: [PATCH 14/21] feat(middleware-auth): add method for anonymous session
 flow

affects: @commercetools/sdk-middleware-auth
---
 docs/sdk/api/sdkMiddlewareAuth.md             | 37 +++++++++++
 .../src/anonymous-session-flow.js             | 37 ++++++++++-
 .../test/anonymous-session-flow.spec.js       | 63 +++++++++++++++++++
 3 files changed, 135 insertions(+), 2 deletions(-)
 create mode 100644 packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js

diff --git a/docs/sdk/api/sdkMiddlewareAuth.md b/docs/sdk/api/sdkMiddlewareAuth.md
index ca25d595b..2978207e7 100644
--- a/docs/sdk/api/sdkMiddlewareAuth.md
+++ b/docs/sdk/api/sdkMiddlewareAuth.md
@@ -129,3 +129,40 @@ const client = createClient({
   ],
 })
 ```
+
+## `createAuthMiddlewareForAnonymousSessionFlow(options)`
+
+Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for the [Anonymous Session Flow](http://dev.commercetools.com/http-api-authorization.html#tokens-for-anonymous-sessions) of the commercetools platform API.
+
+#### Named arguments (options)
+
+1. `host` *(String)*: the host of the OAuth API service
+2. `projectKey` *(String)*: the key of the project to assign the default scope to
+3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret`, `anonymousId`)
+4. `scopes` *(Array)*: a list of [scopes](http://dev.commercetools.com/http-api-authorization.html#scopes) (default `manage_project:{projectKey}`) to assign to the OAuth token
+
+
+#### Usage example
+
+```js
+import { createClient } from '@commercetools/sdk-client'
+import { createAuthMiddlewareForAnonymousSessionFlow } from '@commercetools/sdk-middleware-auth'
+
+const client = createClient({
+  middlewares: [
+    createAuthMiddlewareForAnonymousSessionFlow({
+      host: 'https://auth.commercetools.com',
+      projectKey: 'test',
+      credentials: {
+        clientId: '123',
+        clientSecret: 'secret',
+        anonymousId: 'unique-id-of-customer-not-required',
+      },
+      scopes: [
+        'view_products:test',
+        'manage_orders:test',
+      ],
+    }),
+  ],
+})
+```
diff --git a/packages/sdk-middleware-auth/src/anonymous-session-flow.js b/packages/sdk-middleware-auth/src/anonymous-session-flow.js
index 61ac21d14..61e10bc2f 100644
--- a/packages/sdk-middleware-auth/src/anonymous-session-flow.js
+++ b/packages/sdk-middleware-auth/src/anonymous-session-flow.js
@@ -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)
+  }
 }
diff --git a/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js b/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js
new file mode 100644
index 000000000..cdc75d9d7
--- /dev/null
+++ b/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js
@@ -0,0 +1,63 @@
+import {
+  createAuthMiddlewareForAnonymousSessionFlow,
+} from '../src'
+
+import authMiddlewareBase from '../src/base-auth-flow'
+
+jest.mock('../src/base-auth-flow')
+
+function createTestRequest (options) {
+  return {
+    url: '',
+    method: 'GET',
+    body: null,
+    headers: {},
+    ...options,
+  }
+}
+
+function createTestMiddlewareOptions (options) {
+  return {
+    host: 'https://auth.commercetools.co',
+    projectKey: 'foo',
+    credentials: {
+      clientId: '123',
+      clientSecret: 'secret',
+      anonymousId: 'secretme',
+    },
+    ...options,
+  }
+}
+
+describe('Anonymous Session Flow', () => {
+  it('should call the base-auth-flow method with the right params', () =>
+    new Promise((resolve, reject) => {
+      authMiddlewareBase.mockImplementation((params, next) => {
+        next(params) // makes it easy to test what was passed in
+      })
+      const request = createTestRequest()
+      const response = {
+        resolve,
+        reject,
+      }
+      const next = (actualParams) => {
+        expect(actualParams.request).toEqual(actualParams.request)
+        expect(actualParams.response).toEqual(actualParams.response)
+        expect(actualParams.pendingTasks).toEqual([])
+        expect(actualParams.url).toBe(
+          'https://auth.commercetools.co/oauth/foo/anonymous/token',
+        )
+        expect('MTIzOnNlY3JldA==').toBe(actualParams.basicAuth)
+        expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
+        jest.unmock('../src/base-auth-flow')
+        resolve()
+      }
+      const middlewareOptions = createTestMiddlewareOptions()
+      const authMiddleware = createAuthMiddlewareForAnonymousSessionFlow(
+        middlewareOptions,
+      )
+
+      authMiddleware(next)(request, response)
+    }),
+  )
+})

From 0fea19467b67023e5311efae9cb955adabd933fd Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Mon, 21 Aug 2017 13:24:49 +0200
Subject: [PATCH 15/21] refactor(test): update code

affects: @commercetools/sdk-middleware-auth
---
 .../sdk-middleware-auth/test/anonymous-session-flow.spec.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js b/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js
index cdc75d9d7..6468149c1 100644
--- a/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/anonymous-session-flow.spec.js
@@ -41,13 +41,13 @@ describe('Anonymous Session Flow', () => {
         reject,
       }
       const next = (actualParams) => {
-        expect(actualParams.request).toEqual(actualParams.request)
-        expect(actualParams.response).toEqual(actualParams.response)
+        expect(actualParams.request).toEqual(request)
+        expect(actualParams.response).toEqual(response)
         expect(actualParams.pendingTasks).toEqual([])
         expect(actualParams.url).toBe(
           'https://auth.commercetools.co/oauth/foo/anonymous/token',
         )
-        expect('MTIzOnNlY3JldA==').toBe(actualParams.basicAuth)
+        expect(actualParams.basicAuth).toBe('MTIzOnNlY3JldA==')
         expect(authMiddlewareBase).toHaveBeenCalledTimes(1)
         jest.unmock('../src/base-auth-flow')
         resolve()

From ed81854d14ca8b4c4d683f5581f13f5e859f7f99 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Mon, 21 Aug 2017 15:59:10 +0200
Subject: [PATCH 16/21] refactor(buildRequest): ensure projectKey is present

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/src/build-requests.js | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/packages/sdk-middleware-auth/src/build-requests.js b/packages/sdk-middleware-auth/src/build-requests.js
index bebed7815..f891dac77 100644
--- a/packages/sdk-middleware-auth/src/build-requests.js
+++ b/packages/sdk-middleware-auth/src/build-requests.js
@@ -94,8 +94,13 @@ export function buildRequestForRefreshTokenFlow () {
 }
 
 export function buildRequestForAnonymousSessionFlow (
-  options: AuthMiddlewareOptions = {},
+  options: AuthMiddlewareOptions,
 ): BuiltRequestParams {
+  if (!options)
+    throw new Error('Missing required options')
+
+  if (!options.projectKey)
+    throw new Error('Missing required option (projectKey)')
   const pKey = options.projectKey
   // eslint-disable-next-line no-param-reassign
   options.oauthUri = options.oauthUri || `/oauth/${pKey}/anonymous/token`

From d1c25cbe7091dabfd28fbc5ea503e9cb47dd7da1 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Tue, 22 Aug 2017 12:23:52 +0200
Subject: [PATCH 17/21] test(anonymouse-session): improve test coverage

affects: @commercetools/sdk-middleware-auth
---
 .../test/build-requests.spec.js               | 22 ++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/packages/sdk-middleware-auth/test/build-requests.spec.js b/packages/sdk-middleware-auth/test/build-requests.spec.js
index 346510358..c440fde5c 100644
--- a/packages/sdk-middleware-auth/test/build-requests.spec.js
+++ b/packages/sdk-middleware-auth/test/build-requests.spec.js
@@ -29,7 +29,8 @@ function createTestOptions (options) {
 
 describe('buildRequestForPasswordFlow', () => {
   const body = oneLineTrim`grant_type=password&
-    username=foobar&password=verysecurepassword&
+    username=foobar&
+    password=verysecurepassword&
     scope=${allScopes.join(' ')}
   `
   it('build request values with all the given options', () => {
@@ -116,8 +117,8 @@ describe('buildRequestForPasswordFlow', () => {
   it('validate required option (username, password)', () => {
     const options = createTestOptions({
       credentials: {
-        clientId: 'yeah',
-        clientSecret: 'yo',
+        clientId: 'foo',
+        clientSecret: 'baz',
         user: {
           username: 'bar',
         },
@@ -242,6 +243,21 @@ describe('buildRequestForAnonymousSessionFlow', () => {
     })
   })
 
+  it('validate required options', () => {
+    expect(
+      () => buildRequestForAnonymousSessionFlow(),
+    ).toThrowError('Missing required options')
+  })
+
+  it('validate required option (projectKey)', () => {
+    const options = createTestOptions({
+      projectKey: undefined,
+    })
+    expect(
+      () => buildRequestForAnonymousSessionFlow(options),
+    ).toThrowError('Missing required option (projectKey)')
+  })
+
   it('should add anonymousId if passed in', () => {
     const mockCred = {
       clientId: '123',

From c95bbdb0dc184d7fb4c0d7576c256c7ea407d9fa Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Tue, 22 Aug 2017 12:30:50 +0200
Subject: [PATCH 18/21] docs(auth): improve docs

affects: @commercetools/sdk-middleware-auth
---
 docs/sdk/api/sdkMiddlewareAuth.md                       | 3 ++-
 packages/sdk-middleware-auth/test/password-flow.spec.js | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/docs/sdk/api/sdkMiddlewareAuth.md b/docs/sdk/api/sdkMiddlewareAuth.md
index 2978207e7..0060274b3 100644
--- a/docs/sdk/api/sdkMiddlewareAuth.md
+++ b/docs/sdk/api/sdkMiddlewareAuth.md
@@ -102,7 +102,8 @@ Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for
 
 1. `host` *(String)*: the host of the OAuth API service
 2. `projectKey` *(String)*: the key of the project to assign the default scope to
-3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret`)
+3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret` `user`)
+  - The user field is an object containining `username` and `password`. [Sample below](#usage-example)
 4. `scopes` *(Array)*: a list of [scopes](http://dev.commercetools.com/http-api-authorization.html#scopes) (default `manage_project:{projectKey}`) to assign to the OAuth token
 
 
diff --git a/packages/sdk-middleware-auth/test/password-flow.spec.js b/packages/sdk-middleware-auth/test/password-flow.spec.js
index 89dca8da8..fbc77311a 100644
--- a/packages/sdk-middleware-auth/test/password-flow.spec.js
+++ b/packages/sdk-middleware-auth/test/password-flow.spec.js
@@ -4,7 +4,7 @@ import {
 
 import authMiddlewareBase from '../src/base-auth-flow'
 
-// required to be at the root because Jest hoists it avoid all requires,
+// required to be at the root because Jest hoists it above all requires,
 // if in any method like `beforeAll`,
 // it will be hoisted within the scope of that method
 jest.mock('../src/base-auth-flow')

From 2792091cb877caccc72d43ca80929c1bc3443182 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Tue, 22 Aug 2017 12:33:20 +0200
Subject: [PATCH 19/21] refactor(tests): improve readability

affects: @commercetools/sdk-middleware-auth
---
 packages/sdk-middleware-auth/test/build-requests.spec.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/packages/sdk-middleware-auth/test/build-requests.spec.js b/packages/sdk-middleware-auth/test/build-requests.spec.js
index c440fde5c..b5c46c7e7 100644
--- a/packages/sdk-middleware-auth/test/build-requests.spec.js
+++ b/packages/sdk-middleware-auth/test/build-requests.spec.js
@@ -28,7 +28,8 @@ function createTestOptions (options) {
 }
 
 describe('buildRequestForPasswordFlow', () => {
-  const body = oneLineTrim`grant_type=password&
+  const body = oneLineTrim`
+    grant_type=password&
     username=foobar&
     password=verysecurepassword&
     scope=${allScopes.join(' ')}
@@ -268,7 +269,8 @@ describe('buildRequestForAnonymousSessionFlow', () => {
     expect(buildRequestForAnonymousSessionFlow(options)).toEqual({
       basicAuth: 'MTIzOnNlY3JldA==',
       url: 'http://localhost:8080/oauth/test/anonymous/token',
-      body: oneLineTrim`grant_type=client_credentials&
+      body: oneLineTrim`
+        grant_type=client_credentials&
         scope=${allScopes.join(' ')}&
         anonymous_id=youdontknowme
       `,

From e256305ba57d8ae415e7bf5efa620defc55987c3 Mon Sep 17 00:00:00 2001
From: Abimbola Idowu <abimbola2010@gmail.com>
Date: Tue, 22 Aug 2017 14:56:14 +0200
Subject: [PATCH 20/21] test(integration): add test for anonymouse session flow

---
 integration-tests/sdk/auth.it.js           | 123 +++++++++++++++++++++
 integration-tests/sdk/customer-login.it.js |  71 ------------
 2 files changed, 123 insertions(+), 71 deletions(-)
 create mode 100644 integration-tests/sdk/auth.it.js
 delete mode 100644 integration-tests/sdk/customer-login.it.js

diff --git a/integration-tests/sdk/auth.it.js b/integration-tests/sdk/auth.it.js
new file mode 100644
index 000000000..fdf31551b
--- /dev/null
+++ b/integration-tests/sdk/auth.it.js
@@ -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)
+  })
+})
diff --git a/integration-tests/sdk/customer-login.it.js b/integration-tests/sdk/customer-login.it.js
deleted file mode 100644
index da1095266..000000000
--- a/integration-tests/sdk/customer-login.it.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { createClient } from '@commercetools/sdk-client'
-import { getCredentials } from '@commercetools/get-credentials'
-import {
-  createAuthMiddlewareForPasswordFlow,
-} 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 = 'customers-login-integration-test'
-else
-  projectKey = process.env.npm_config_projectkey
-
-describe('Customer Login', () => {
-  const httpMiddleware = createHttpMiddleware({
-    host: 'https://api.sphere.io',
-  })
-  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(() => createData(apiConfig, 'customers', [{
-      email: userEmail,
-      password: userPassword,
-    }])),
-  )
-  afterAll(() => clearData(apiConfig, 'customers'))
-
-  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)
-    })
-  })
-})

From 42077a609df89c2f486cf7cddfad6a457edc5372 Mon Sep 17 00:00:00 2001
From: wizzy25 <womayuku@gmail.com>
Date: Tue, 22 Aug 2017 15:35:12 +0200
Subject: [PATCH 21/21] docs(sdk-middleware-auth): update documentation

affects: @commercetools/sdk-middleware-auth
---
 docs/sdk/api/sdkMiddlewareAuth.md | 38 +------------------------------
 1 file changed, 1 insertion(+), 37 deletions(-)

diff --git a/docs/sdk/api/sdkMiddlewareAuth.md b/docs/sdk/api/sdkMiddlewareAuth.md
index 0060274b3..6672abbd4 100644
--- a/docs/sdk/api/sdkMiddlewareAuth.md
+++ b/docs/sdk/api/sdkMiddlewareAuth.md
@@ -62,6 +62,7 @@ Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for
 
 1. `host` *(String)*: the host of the OAuth API service
 2. `projectKey` *(String)*: the key of the project to assign the default scope to
+   - The user field is an object containining `username` and `password`. [Sample below](#usage-example)
 3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret`)
 4. `scopes` *(Array)*: a list of [scopes](http://dev.commercetools.com/http-api-authorization.html#scopes) to assign to the OAuth token. _No default scope is sent_
 
@@ -94,43 +95,6 @@ const client = createClient({
 })
 ```
 
-## `createAuthMiddlewareForPasswordFlow(options)`
-
-Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for the [Password Flow](http://dev.commercetools.com/http-api-authorization.html#password-flow) of the commercetools platform API.
-
-#### Named arguments (options)
-
-1. `host` *(String)*: the host of the OAuth API service
-2. `projectKey` *(String)*: the key of the project to assign the default scope to
-3. `credentials` *(Object)*: the client credentials for authentication (`clientId`, `clientSecret` `user`)
-  - The user field is an object containining `username` and `password`. [Sample below](#usage-example)
-4. `scopes` *(Array)*: a list of [scopes](http://dev.commercetools.com/http-api-authorization.html#scopes) (default `manage_project:{projectKey}`) to assign to the OAuth token
-
-
-#### Usage example
-
-```js
-import { createClient } from '@commercetools/sdk-client'
-import { createAuthMiddlewareForPasswordFlow } from '@commercetools/sdk-middleware-auth'
-
-const client = createClient({
-  middlewares: [
-    createAuthMiddlewareForPasswordFlow({
-      host: 'https://auth.commercetools.com',
-      projectKey: 'test',
-      credentials: {
-        clientId: '123',
-        clientSecret: 'secret',
-      },
-      scopes: [
-        'view_products:test',
-        'manage_orders:test',
-      ],
-    }),
-  ],
-})
-```
-
 ## `createAuthMiddlewareForAnonymousSessionFlow(options)`
 
 Creates a [middleware](/sdk/Glossary.md#middleware) to handle authentication for the [Anonymous Session Flow](http://dev.commercetools.com/http-api-authorization.html#tokens-for-anonymous-sessions) of the commercetools platform API.