parent
5e56e072c1
commit
b2a95e3bb8
@ -1,85 +1,108 @@ |
|||||||
import ApolloClient, { gql } from "apollo-boost" |
import { gql } from "apollo-server-express" |
||||||
|
import { GraphQLClient, rawRequest } from "graphql-request" |
||||||
import fetch from "node-fetch" |
import fetch from "node-fetch" |
||||||
import { createConnection } from "typeorm" |
import { createConnection } from "typeorm" |
||||||
import { createServer } from "./server" |
import { createServer } from "./server" |
||||||
import { |
import { gqlToString } from "./server/schema" |
||||||
initializeRollbackTransactions, |
import { testingConnectionOptions } from "./server/testing" |
||||||
runInRollbackTransaction, |
import { AccessToken } from "./server/userResolver/AccessToken" |
||||||
testingConnectionOptions, |
import { verifiedRefreshTokenPayload } from "./server/userResolver/auth" |
||||||
} from "./server/testing" |
import { User } from "./server/userResolver/User" |
||||||
|
import cookie = require("cookie") |
||||||
const port = 4001 |
|
||||||
|
|
||||||
beforeAll(async () => { |
|
||||||
initializeRollbackTransactions() |
|
||||||
await createConnection(testingConnectionOptions()) |
|
||||||
await createServer(port) |
|
||||||
}) |
|
||||||
|
|
||||||
describe("server should", () => { |
describe("server should", () => { |
||||||
it( |
it("perform the refresh tokens operation flawlessly", async () => { |
||||||
"handle auth user me request", |
const halfADay = (60 * 60 * 24) / 2 |
||||||
runInRollbackTransaction(async () => { |
const fifteenDays = 60 * 60 * 24 * 15 |
||||||
const uri = `http://localhost:${port}/graphql` |
|
||||||
let client = new ApolloClient({ uri, fetch }) |
|
||||||
|
|
||||||
const createUserMutation = gql` |
|
||||||
mutation { |
|
||||||
createUser(email: "email@email.com", password: "password") { |
|
||||||
email |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
||||||
await client.mutate({ mutation: createUserMutation }) |
|
||||||
|
|
||||||
const loginTokensQuery = gql` |
const createUserResponse = await rawRequest( |
||||||
query { |
gqlUri, |
||||||
loginTokens(email: "email@email.com", password: "password") { |
gqlToString(createUserMutation) |
||||||
accessToken |
) |
||||||
} |
const userId = createUserResponse.data.createUser.id |
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
const tokens = await client.query({ query: loginTokensQuery }) |
const accessTokenReponse = await rawRequest(gqlUri, gqlToString(accessTokenQuery)) |
||||||
const accessToken = tokens.data.loginTokens.accessToken |
const accessToken: AccessToken = accessTokenReponse.data.accessToken |
||||||
|
const headers: Headers = accessTokenReponse.headers |
||||||
|
const cookieHeader = headers.get("set-cookie") as string |
||||||
|
const parsedCookie = cookie.parse(cookieHeader) |
||||||
|
const refreshCookieExpires = dateInKiloSeconds(parsedCookie.Expires) |
||||||
|
const refreshTokenPayload = verifiedRefreshTokenPayload(parsedCookie.rt) |
||||||
|
const jwtLifetime = refreshTokenPayload.exp! - refreshTokenPayload.iat! |
||||||
|
const refLifetime = dateInKiloSeconds(new Date().getTime() + jwtLifetime * 1000) |
||||||
|
|
||||||
client = new ApolloClient({ |
const client = new GraphQLClient(gqlUri, { |
||||||
uri, |
headers: { |
||||||
fetch, |
Authorization: "Bearer " + accessToken.jwt, |
||||||
request: operation => { |
}, |
||||||
operation.setContext({ |
}) |
||||||
headers: { |
const meResponse = await client.rawRequest(gqlToString(meQuery)) |
||||||
authorization: "Bearer " + accessToken, |
|
||||||
}, |
|
||||||
}) |
|
||||||
}, |
|
||||||
}) |
|
||||||
|
|
||||||
const meQuery = gql` |
const response = await fetch(refreshTokenUri, { |
||||||
query { |
method: "POST", |
||||||
me { |
headers: { cookie: cookieHeader }, |
||||||
email |
}) |
||||||
} |
const jsonResponse = await response.json() |
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
const meResponse = await client.query({ query: meQuery }) |
expect(cookieHeader).toMatch(/HttpOnly/) |
||||||
const meEmail = meResponse.data.me.email |
expect(parsedCookie.Path).toBe("/refresh_token") |
||||||
|
expect(refreshTokenPayload.userId).toBe(userId) |
||||||
|
expect(refreshCookieExpires).toBeCloseTo(refLifetime) |
||||||
|
expect(jwtLifetime).toBeGreaterThanOrEqual(halfADay) |
||||||
|
expect(jwtLifetime).not.toBeGreaterThan(fifteenDays) |
||||||
|
expect(meResponse.data.me.email).toBe("auth@server.com") |
||||||
|
expect(jsonResponse.data).toBeDefined() |
||||||
|
expect(jsonResponse.errors).toBeUndefined() |
||||||
|
}) |
||||||
|
|
||||||
expect(meEmail).toBe("email@email.com") |
it("it doesnt perform refresh tokens without valid cookie", async () => { |
||||||
|
const response = await fetch(refreshTokenUri, { |
||||||
|
method: "POST", |
||||||
|
headers: { cookie: "INVALID-COOKIE" }, |
||||||
}) |
}) |
||||||
) |
const jsonResponse = await response.json() |
||||||
|
|
||||||
it( |
expect(jsonResponse.data).toBeNull() |
||||||
"receive no refresh token without auth header", |
expect(jsonResponse.errors).not.toBeUndefined() |
||||||
runInRollbackTransaction(async () => { |
}) |
||||||
const uri = `http://localhost:${port}/refresh_token` |
}) |
||||||
|
|
||||||
const response = await fetch(uri, { method: "POST" }) |
beforeAll(async () => { |
||||||
const jsonResponse = await response.json() |
await createConnection(testingConnectionOptions()) |
||||||
|
await createServer(port) |
||||||
|
}) |
||||||
|
|
||||||
expect(jsonResponse.data).toBeNull() |
afterAll(async () => { |
||||||
expect(jsonResponse.errors).not.toBeUndefined() |
User.delete({ email: "auth@server.com" }) |
||||||
}) |
|
||||||
) |
|
||||||
}) |
}) |
||||||
|
|
||||||
|
const port = 4001 |
||||||
|
const gqlUri = `http://localhost:${port}/graphql` |
||||||
|
const refreshTokenUri = `http://localhost:${port}/refresh_token` |
||||||
|
|
||||||
|
const createUserMutation = gql` |
||||||
|
mutation { |
||||||
|
createUser(email: "auth@server.com", password: "password") { |
||||||
|
email |
||||||
|
id |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const accessTokenQuery = gql` |
||||||
|
query { |
||||||
|
accessToken(email: "auth@server.com", password: "password") { |
||||||
|
jwt |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const meQuery = gql` |
||||||
|
query { |
||||||
|
me { |
||||||
|
email |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
const dateInKiloSeconds = (date: string | number) => new Date(date).getTime() / 1000000 |
||||||
|
@ -1,8 +0,0 @@ |
|||||||
import { Request, Response } from "express" |
|
||||||
import { ContextPayload } from "./auth" |
|
||||||
|
|
||||||
export interface ContextInterface { |
|
||||||
req: Request |
|
||||||
res: Response |
|
||||||
payload?: ContextPayload |
|
||||||
} |
|
Loading…
Reference in new issue