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 { createConnection } from "typeorm" |
||||
import { createServer } from "./server" |
||||
import { |
||||
initializeRollbackTransactions, |
||||
runInRollbackTransaction, |
||||
testingConnectionOptions, |
||||
} from "./server/testing" |
||||
|
||||
const port = 4001 |
||||
|
||||
beforeAll(async () => { |
||||
initializeRollbackTransactions() |
||||
await createConnection(testingConnectionOptions()) |
||||
await createServer(port) |
||||
}) |
||||
import { gqlToString } from "./server/schema" |
||||
import { testingConnectionOptions } from "./server/testing" |
||||
import { AccessToken } from "./server/userResolver/AccessToken" |
||||
import { verifiedRefreshTokenPayload } from "./server/userResolver/auth" |
||||
import { User } from "./server/userResolver/User" |
||||
import cookie = require("cookie") |
||||
|
||||
describe("server should", () => { |
||||
it( |
||||
"handle auth user me request", |
||||
runInRollbackTransaction(async () => { |
||||
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 }) |
||||
it("perform the refresh tokens operation flawlessly", async () => { |
||||
const halfADay = (60 * 60 * 24) / 2 |
||||
const fifteenDays = 60 * 60 * 24 * 15 |
||||
|
||||
const loginTokensQuery = gql` |
||||
query { |
||||
loginTokens(email: "email@email.com", password: "password") { |
||||
accessToken |
||||
} |
||||
} |
||||
` |
||||
const createUserResponse = await rawRequest( |
||||
gqlUri, |
||||
gqlToString(createUserMutation) |
||||
) |
||||
const userId = createUserResponse.data.createUser.id |
||||
|
||||
const tokens = await client.query({ query: loginTokensQuery }) |
||||
const accessToken = tokens.data.loginTokens.accessToken |
||||
const accessTokenReponse = await rawRequest(gqlUri, gqlToString(accessTokenQuery)) |
||||
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({ |
||||
uri, |
||||
fetch, |
||||
request: operation => { |
||||
operation.setContext({ |
||||
headers: { |
||||
authorization: "Bearer " + accessToken, |
||||
}, |
||||
}) |
||||
}, |
||||
}) |
||||
const client = new GraphQLClient(gqlUri, { |
||||
headers: { |
||||
Authorization: "Bearer " + accessToken.jwt, |
||||
}, |
||||
}) |
||||
const meResponse = await client.rawRequest(gqlToString(meQuery)) |
||||
|
||||
const meQuery = gql` |
||||
query { |
||||
me { |
||||
email |
||||
} |
||||
} |
||||
` |
||||
const response = await fetch(refreshTokenUri, { |
||||
method: "POST", |
||||
headers: { cookie: cookieHeader }, |
||||
}) |
||||
const jsonResponse = await response.json() |
||||
|
||||
const meResponse = await client.query({ query: meQuery }) |
||||
const meEmail = meResponse.data.me.email |
||||
expect(cookieHeader).toMatch(/HttpOnly/) |
||||
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( |
||||
"receive no refresh token without auth header", |
||||
runInRollbackTransaction(async () => { |
||||
const uri = `http://localhost:${port}/refresh_token` |
||||
expect(jsonResponse.data).toBeNull() |
||||
expect(jsonResponse.errors).not.toBeUndefined() |
||||
}) |
||||
}) |
||||
|
||||
const response = await fetch(uri, { method: "POST" }) |
||||
const jsonResponse = await response.json() |
||||
beforeAll(async () => { |
||||
await createConnection(testingConnectionOptions()) |
||||
await createServer(port) |
||||
}) |
||||
|
||||
expect(jsonResponse.data).toBeNull() |
||||
expect(jsonResponse.errors).not.toBeUndefined() |
||||
}) |
||||
) |
||||
afterAll(async () => { |
||||
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