-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Improve client auth options (#115)
## What does this PR do? Allows authorisation via the `CoreDomainClient` using JWT, headers (public users) or admin secret ## Next steps... Update all references in `planx-new`, try to instantiate one client per-request in Express
- Loading branch information
1 parent
0ff911c
commit 03db128
Showing
4 changed files
with
80 additions
and
57 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 |
---|---|---|
@@ -1,25 +1,66 @@ | ||
import { GraphQLClient } from "graphql-request"; | ||
|
||
export function graphQLClient({ | ||
url, | ||
secret, | ||
authorizedSession, | ||
}: { | ||
url: string; | ||
secret?: string; | ||
authorizedSession?: { | ||
interface JWTAuth { | ||
jwt: string; | ||
} | ||
|
||
interface SessionAuth { | ||
session: { | ||
email: string; | ||
sessionId: string; | ||
}; | ||
} | ||
|
||
interface AdminAuth { | ||
adminSecret: string; | ||
} | ||
|
||
export type Auth = JWTAuth | SessionAuth | AdminAuth; | ||
|
||
/** | ||
* Client which queries using user's JWT for role-bases access to Hasura | ||
* Should be used for all requests made my authorised users | ||
*/ | ||
const getRoleBasedClient = (url: string, auth: JWTAuth) => | ||
new GraphQLClient(url, { headers: { authorization: `Bearer ${auth.jwt}` } }); | ||
|
||
/** | ||
* Session based client which allows non-authorised users access to their session | ||
* Used for Save & Return | ||
*/ | ||
const getSessionClient = (url: string, auth: SessionAuth) => | ||
new GraphQLClient(url, { | ||
headers: { | ||
"x-hasura-lowcal-session-id": auth.session.sessionId, | ||
"x-hasura-lowcal-email": auth.session.email, | ||
}, | ||
}); | ||
|
||
/** | ||
* Admin client with full access to Hasura | ||
* Should be used with caution - only for testing / scripting | ||
* @deprecated Consider moving to an "api" role in Hasura | ||
*/ | ||
const getAdminClient = (url: string, auth: AdminAuth) => | ||
new GraphQLClient(url, { | ||
headers: { "x-hasura-admin-secret": auth.adminSecret }, | ||
}); | ||
|
||
export function getGraphQLClient({ | ||
url, | ||
auth, | ||
}: { | ||
url: string; | ||
auth?: Auth; | ||
}): GraphQLClient { | ||
let headers = {}; | ||
if (secret) { | ||
headers = { "x-hasura-admin-secret": secret }; | ||
} else if (authorizedSession) { | ||
headers = { | ||
"x-hasura-lowcal-session-id": authorizedSession.sessionId, | ||
"x-hasura-lowcal-email": authorizedSession.email, | ||
}; | ||
} | ||
return new GraphQLClient(url, { headers }); | ||
// Return public client by default | ||
if (!auth) return new GraphQLClient(url); | ||
|
||
if ("jwt" in auth) return getRoleBasedClient(url, auth); | ||
if ("session" in auth) return getSessionClient(url, auth); | ||
if ("adminSecret" in auth) return getAdminClient(url, auth); | ||
|
||
throw Error( | ||
"Unable to instantiate GraphQL client - insufficient auth details provided", | ||
); | ||
} |
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 |
---|---|---|
|
@@ -11,35 +11,35 @@ describe("CoreDomainClient", () => { | |
expect(core).toBeInstanceOf(CoreDomainClient); | ||
}); | ||
|
||
test("instantiating a client with a secret", () => { | ||
const core = new CoreDomainClient({ hasuraSecret: "shhh..." }); | ||
test("instantiating a client with an admin secret", () => { | ||
const auth = { adminSecret: "shhh..." }; | ||
const core = new CoreDomainClient({ auth }); | ||
expect(core).toBeInstanceOf(CoreDomainClient); | ||
}); | ||
|
||
test("instantiating a client with a URL and a secret", () => { | ||
test("instantiating a client with a URL and an admin secret", () => { | ||
const auth = { adminSecret: "shhh..." }; | ||
const core = new CoreDomainClient({ | ||
hasuraSecret: "shhh...", | ||
targetURL: "https://example.com", | ||
auth, | ||
}); | ||
expect(core).toBeInstanceOf(CoreDomainClient); | ||
}); | ||
|
||
test("a public client can authorize a session", () => { | ||
const core = new CoreDomainClient(); | ||
core.authorizeSession({ email: "[email protected]", sessionId: "1234" }); | ||
test("instantiating a client with session details", () => { | ||
const auth = { session: { email: "[email protected]", sessionId: "1234" } }; | ||
const core = new CoreDomainClient({ auth }); | ||
expect(core.client.requestConfig.headers).toEqual({ | ||
"x-hasura-lowcal-session-id": "1234", | ||
"x-hasura-lowcal-email": "[email protected]", | ||
}); | ||
}); | ||
|
||
test("an admin client cannot authorize a session", () => { | ||
const core = new CoreDomainClient({ | ||
hasuraSecret: "shhh...", | ||
targetURL: "https://example.com", | ||
test("instantiating a client with a JSON web token", () => { | ||
const auth = { jwt: "ABC123" }; | ||
const core = new CoreDomainClient({ auth }); | ||
expect(core.client.requestConfig.headers).toEqual({ | ||
authorization: "Bearer ABC123", | ||
}); | ||
expect(() => | ||
core.authorizeSession({ email: "[email protected]", sessionId: "1234" }), | ||
).toThrow(); | ||
}); | ||
}); |
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