Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
chore: tidy up examples, add section about examples to readme, add he…
Browse files Browse the repository at this point in the history
…lper scripts for configuring examples
  • Loading branch information
darahayes committed Nov 13, 2019
1 parent ab33d66 commit 69ddd8d
Show file tree
Hide file tree
Showing 10 changed files with 531 additions and 99 deletions.
147 changes: 147 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,150 @@ The `examples` folder contains runnable examples that demonstrate the various wa
* `examples/authMiddlewares` - Shows usage of the `auth` and `hasRole` middlewares.
* `subscriptions` - Shows basic subscriptions setup, requiring all subscriptions to be authenticated.
* `subscriptionsAdvanced` - Shows subscriptions that use the `auth` and `hasRole` middlewares directly on subscription resolvers.
## Setting up the Examples
Prerequisites:
* Docker and docker-compose installed
* Node.js and NPM installed
Start by cloning this repo.
```
git clone https://github.com/aerogear/keycloak-connect-graphql/
```
Then start a Keycloak server using `docker-compose`.
```
cd examples/config && docker-compose up
```
Now in a separate terminal, seed the keycloak server with a sample configuration.
```
$ npm run examples:seed

creating role admin
creating role developer
creating client role admin for client keycloak-connect-graphql-bearer
creating client role developer for client keycloak-connect-graphql-bearer
creating client role admin for client keycloak-connect-graphql-public
creating client role developer for client keycloak-connect-graphql-public
creating user developer with password developer
assigning client and realm roles called "developer" to user developer
creating user admin with password admin
assigning client and realm roles called "admin" to user admin
done
```
This creates a sample realm called `keycloak-connect-graphql` with some clients, roles and users that we can use in the examples.
Now we are ready to start and explore the examples.
The Keycloak console is accessible at [localhost:8080](http://localhost:8080) and the admin login is `admin/admin`. You can make any configuration changes you wish and `npm run examples:seed` will always recreate the example realm from scratch
## Running the Basic Example
The basic example shows:
* The setup of the keycloak express middleware
* How to add **Role Based Access Control** using the `@hasRole` schema directive.
In `examples/basic.js` the GraphQL schema for the server is defined:
```js
const typeDefs = gql`
type Query {
hello: String @hasRole(role: "developer")
}
`
```
The `@hasRole` directive means only users with the `developer` role are authorized to perform the `hello` query. Start the server to try it out.
```
$ node examples/basic.js
🚀 Server ready at http://localhost:4000/graphql
```
Open the URL and you will see the Keycloak login screen. First login with `developer/developer` as the username/password.
Now you should see the GraphQL Playground.
NOTE: We initially saw the Keycloak login screen because the keycloak middleware is protecting the `/graphql` endpoint using a `public` client configuration. We're using a public client here because we want to access the GraphQL Playground in our browser. In production your GraphQL API would use a `bearer` client configuration.
On the right side of the GraphQL Playground you will see a message:
```
{
"error": "Failed to fetch. Please check your connection"
}
```
Although the browser has authenticated with the Keycloak server, the GraphQL playround isn't sending the keycloak `Authorization` header along with its requests to the GraphQL server. In the bottom left corner of the playground there is a field called **HTTP Headers** which will be added to requests sent by the playground.
Use `scripts/getToken.js` to get a valid header for the `developer` user.
```
node scripts/getToken.js developer developer # username password

{"Authorization":"Bearer <token string>"}
```
Copy the entire JSON object, then paste it into the HTTP Headers field in the playground. The error message should disappear.
Now try the following query:
```
query {
hello
}
```
You should see the result.
```
{
"data": {
"hello": "Hello developer"
}
}
```
The `hasRole` directive checked that the user had the appropriate role and then the GraphQL resolver successfully executed. Let's change the role. Change the code in `examples/basic.js` to the code below and then restart the server.
```js
const typeDefs = gql`
type Query {
hello: String @hasRole(role: "admin")
}
`
```
Now run the query in the playground again. You should see an error.
```
{
"errors": [
{
"message": "User is not authorized. Must have one of the following roles: [admin]",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"hello"
],
"extensions": <omitted>
}
],
"data": {
"hello": null
}
}
```
This time an error comes back saying the user does not have the right role. That's the full example! The process of running and trying the other examples is very similar. Feel free to try them or to look at the code!
3 changes: 2 additions & 1 deletion examples/authMiddlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const { configureKeycloak } = require('./lib/common')
const {
KeycloakContext,
KeycloakTypeDefs,
KeycloakSchemaDirectives
auth,
hasRole
} = require('../')

const app = express()
Expand Down
4 changes: 2 additions & 2 deletions examples/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ app.use(graphqlPath, keycloak.protect())

const typeDefs = gql`
type Query {
hello: String @hasRole(role: "developer")
hello: String @hasRole(role: "admin")
}
`

Expand All @@ -29,7 +29,7 @@ const resolvers = {
hello: (obj, args, context, info) => {
// log some of the auth related info added to the context
console.log(context.kauth.isAuthenticated())
console.log(context.kauth.accessToken.content.name)
console.log(context.kauth.accessToken.content.preferred_username)

const name = context.kauth.accessToken.content.preferred_username || 'world'
return `Hello ${name}`
Expand Down
4 changes: 2 additions & 2 deletions examples/config/keycloak.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"realm": "voyager-testing",
"realm": "keycloak-connect-graphql",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "none",
"resource": "voyager-testing-public",
"resource": "keycloak-connect-graphql-public",
"public-client": true,
"use-resource-role-mappings": true,
"confidential-port": 0
Expand Down

0 comments on commit 69ddd8d

Please sign in to comment.