2019-01-21 17:01:40 +00:00
[[_nodejs_adapter]]
2016-09-02 20:25:29 +00:00
=== Node.js Adapter
2018-08-20 08:12:54 +00:00
{project_name} provides a Node.js adapter built on top of https://github.com/senchalabs/connect[Connect] to protect server-side JavaScript apps - the goal was to be flexible enough to integrate with frameworks like https://expressjs.com/[Express.js].
2016-09-28 12:09:09 +00:00
2017-08-28 12:50:14 +00:00
ifeval::[{project_community}==true]
The library can be downloaded directly from https://www.npmjs.com/package/keycloak-connect[ {project_name} organization] and the source is available at
2016-09-02 20:25:29 +00:00
https://github.com/keycloak/keycloak-nodejs-connect[GitHub].
2017-08-28 12:50:14 +00:00
endif::[]
2016-09-02 20:25:29 +00:00
2017-08-28 12:50:14 +00:00
To use the Node.js adapter, first you must create a client for your application in the {project_name} Administration Console. The adapter supports public, confidential, and bearer-only access type. Which one to choose depends on the use-case scenario.
2016-09-02 20:25:29 +00:00
2017-08-28 12:50:14 +00:00
Once the client is created click the `Installation` tab, select `{project_name} OIDC JSON` for `Format Option`, and then click `Download`. The downloaded `keycloak.json` file should be at the root folder of your project.
2016-09-02 20:25:29 +00:00
==== Installation
Assuming you've already installed https://nodejs.org[Node.js], create a folder for your application:
mkdir myapp && cd myapp
2017-08-28 12:50:14 +00:00
Use `npm init` command to create a `package.json` for your application. Now add the {project_name} connect adapter in the dependencies list:
2016-11-28 19:24:56 +00:00
2017-08-28 12:50:14 +00:00
ifeval::[{project_community}==true]
2016-11-28 19:24:56 +00:00
2016-12-02 14:48:02 +00:00
[source,json,subs="attributes"]
----
2017-03-22 12:33:07 +00:00
"dependencies": {
2017-08-28 12:50:14 +00:00
"keycloak-connect": "{project_versionNpm}"
2016-11-28 19:24:56 +00:00
}
2016-12-02 14:48:02 +00:00
----
2016-11-28 19:24:56 +00:00
2017-08-28 12:50:14 +00:00
endif::[]
2016-11-28 19:24:56 +00:00
2017-08-28 12:50:14 +00:00
ifeval::[{project_product}==true]
2016-11-28 19:24:56 +00:00
2016-12-02 14:48:02 +00:00
[source,json,subs="attributes"]
----
2017-03-22 12:33:07 +00:00
"dependencies": {
2017-08-28 12:50:14 +00:00
"keycloak-connect": "file:keycloak-connect-{project_versionNpm}.tgz"
2016-11-28 19:24:56 +00:00
}
2016-12-02 14:48:02 +00:00
----
2016-09-02 20:25:29 +00:00
2017-08-28 12:50:14 +00:00
endif::[]
2016-09-02 20:25:29 +00:00
==== Usage
Instantiate a Keycloak class::
The `Keycloak` class provides a central point for configuration
and integration with your application. The simplest creation
involves no arguments.
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2017-04-06 20:07:42 +00:00
var session = require('express-session');
2017-02-17 12:26:59 +00:00
var Keycloak = require('keycloak-connect');
2017-04-06 20:07:42 +00:00
var memoryStore = new session.MemoryStore();
var keycloak = new Keycloak({ store: memoryStore });
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
By default, this will locate a file named `keycloak.json` alongside
the main executable of your application to initialize keycloak-specific
settings (public key, realm name, various URLs). The `keycloak.json` file
2017-08-28 12:50:14 +00:00
is obtained from the {project_name} Admin Console.
2016-09-02 20:25:29 +00:00
Instantiation with this method results in all of the reasonable defaults
2017-06-15 09:48:01 +00:00
being used. As alternative, it's also possible to provide a configuration
object, rather than the `keycloak.json` file:
[source,javascript]
----
let kcConfig = {
2017-12-22 05:28:59 +00:00
clientId: 'myclient',
bearerOnly: true,
serverUrl: 'http://localhost:8080/auth',
realm: 'myrealm',
realmPublicKey: 'MIIBIjANB...'
};
let keycloak = new Keycloak({ store: memoryStore }, kcConfig);
2017-06-15 09:48:01 +00:00
----
2018-10-08 23:27:36 +00:00
Applications can also redirect users to their preferred identity provider by using:
[source,javascript]
----
let keycloak = new Keycloak({ store: memoryStore, idpHint: myIdP }, kcConfig);
----
2016-09-02 20:25:29 +00:00
Configuring a web session store::
2017-03-02 22:03:52 +00:00
If you want to use web sessions to manage
server-side state for authentication, you need to initialize the
2016-09-02 20:25:29 +00:00
`Keycloak(...)` with at least a `store` parameter, passing in the actual
session store that `express-session` is using.
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2016-09-02 20:25:29 +00:00
var session = require('express-session');
var memoryStore = new session.MemoryStore();
var keycloak = new Keycloak({ store: memoryStore });
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
Passing a custom scope value::
2017-08-28 12:50:14 +00:00
By default, the scope value `openid` is passed as a query parameter to {project_name}'s login URL, but you can add an additional custom value:
2017-03-02 22:03:52 +00:00
[source,javascript]
2016-09-02 20:25:29 +00:00
var keycloak = new Keycloak({ scope: 'offline_access' });
2017-03-02 22:03:52 +00:00
==== Installing Middleware
2016-09-02 20:25:29 +00:00
Once instantiated, install the middleware into your connect-capable app:
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2016-09-02 20:25:29 +00:00
var app = express();
app.use( keycloak.middleware() );
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
2017-03-02 22:03:52 +00:00
==== Protecting Resources
2016-09-02 20:25:29 +00:00
Simple authentication::
2018-05-29 08:02:18 +00:00
To enforce that a user must be authenticated before accessing a resource,
2016-09-02 20:25:29 +00:00
simply use a no-argument version of `keycloak.protect()`:
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2016-09-02 20:25:29 +00:00
app.get( '/complain', keycloak.protect(), complaintHandler );
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
Role-based authorization::
To secure a resource with an application role for the current app:
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2016-09-02 20:25:29 +00:00
app.get( '/special', keycloak.protect('special'), specialHandler );
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
To secure a resource with an application role for a *different* app:
2017-03-02 22:03:52 +00:00
[source,javascript]
2018-07-02 13:09:49 +00:00
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );
2016-09-02 20:25:29 +00:00
To secure a resource with a realm role:
2017-03-02 22:03:52 +00:00
[source,javascript]
2016-09-02 20:25:29 +00:00
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
Advanced authorization::
To secure resources based on parts of the URL itself, assuming a role exists
for each section:
2017-03-02 22:03:52 +00:00
[source,javascript]
----
2016-09-02 20:25:29 +00:00
function protectBySection(token, request) {
return token.hasRole( request.params.section );
}
2017-03-02 22:03:52 +00:00
2016-09-02 20:25:29 +00:00
app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );
2017-03-02 22:03:52 +00:00
----
2016-09-02 20:25:29 +00:00
==== Additional URLs
Explicit user-triggered logout::
By default, the middleware catches calls to `/logout` to send the user through a
2017-08-28 12:50:14 +00:00
{project_name}-centric logout workflow. This can be changed by specifying a `logout`
2016-09-02 20:25:29 +00:00
configuration parameter to the `middleware()` call:
2017-03-02 22:03:52 +00:00
[source,javascript]
2016-09-02 20:25:29 +00:00
app.use( keycloak.middleware( { logout: '/logoff' } ));
2017-08-28 12:50:14 +00:00
{project_name} Admin Callbacks::
2016-09-02 20:25:29 +00:00
2017-08-28 12:50:14 +00:00
Also, the middleware supports callbacks from the {project_name} console to log out a single
2016-09-02 20:25:29 +00:00
session or all sessions. By default, these type of admin callbacks occur relative
to the root URL of `/` but can be changed by providing an `admin` parameter
to the `middleware()` call:
2017-03-02 22:03:52 +00:00
[source,javascript]
2016-09-02 20:25:29 +00:00
app.use( keycloak.middleware( { admin: '/callbacks' } );