This repository has been archived by the owner on Apr 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
directiveResolvers.ts
118 lines (113 loc) · 3.18 KB
/
directiveResolvers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { CONTEXT_KEY } from '../KeycloakContext'
import { isAuthorizedByRole } from './utils'
/**
*
* @param next - The resolver function you want to wrap with the auth resolver
*
* Checks if the incoming request to the GraphQL server is authenticated.
* Does this by checking that `context.kauth` is present and that the token is valid.
* The keycloak middleware must be set up on your GraphQL endpoint.
*
* Example usage:
*
* ```javascript
* const { auth } = require('keycloak-connect-graphql')
*
* const typeDefs = gql`
* type Query {
* hello: String
* }
* `
*
* const hello = (root, args, context, info) => 'Hello World'
*
* const resolvers = {
* hello: auth(hello)
* }
*
* const server = new ApolloServer({
* typeDefs,
* resolvers,
* schemaDirectives: [KeycloakSchemaDirectives],
* context: ({ req }) => {
* return {
* kauth: new KeycloakContext({ req })
* }
* }
* })
* ```
*
*/
export const auth = (next: Function) => (...params: any[]) => {
let context = params[2]
if (!context[CONTEXT_KEY] || !context[CONTEXT_KEY].isAuthenticated()) {
const error: any = new Error(`User not Authenticated`);
error.code = "UNAUTHENTICATED"
throw error
}
return next.apply( null, params )
}
/**
*
* @param roles - The role or array of roles you want to authorize the user against.
*
* Checks if the authenticated keycloak user has the role.
* If the user has the role, the next resolver is called.
* If the user does not have the role, an error is thrown.
*
* If an array of roles is passed, it checks that the user has at least one of the roles
*
* By default, hasRole checks for keycloak client roles.
* Example: `hasRole('admin')` will check the logged in user has the client role named admin.
*
* It also is possible to check for realm roles and application roles.
* * `hasRole('realm:admin')` will check the logged in user has the admin realm role
* * `hasRole('some-other-app:admin')` will check the loged in user has the admin realm role in a different application
*
*
* Example usage:
*
* ```javascript
* const { hasRole } = require('keycloak-connect-graphql')
*
* const typeDefs = gql`
* type Query {
* hello: String
* }
* `
*
* const hello = (root, args, context, info) => 'Hello World'
*
* const resolvers = {
* hello: hasRole('admin')(hello)
* }
*
* const server = new ApolloServer({
* typeDefs,
* resolvers,
* schemaDirectives: [KeycloakSchemaDirectives],
* context: ({ req }) => {
* return {
* kauth: new KeycloakContext({ req })
* }
* }
* })
* ```
*/
export const hasRole = (roles: Array<string>) => (next: Function) => (...params: any[]) => {
let context = params[2]
if (!context[CONTEXT_KEY] || !context[CONTEXT_KEY].isAuthenticated()) {
const error: any = new Error(`User not Authenticated`);
error.code = "UNAUTHENTICATED"
throw error
}
if (typeof roles === 'string') {
roles = [roles]
}
if (!isAuthorizedByRole(roles, context)) {
const error: any = new Error(`User is not authorized. Must have one of the following roles: [${roles}]`);
error.code = "FORBIDDEN"
throw error
}
return next.apply( null, params )
}