[[_nodejs_adapter]]
=== Node.js Adapter

{{book.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].

{% if book.community %}
The library can be downloaded directly from https://www.npmjs.com/package/keycloak-connect[ {{book.project.name}} organization] and the source is available at
https://github.com/keycloak/keycloak-nodejs-connect[GitHub].
{% endif %}

To use the Node.js adapter, first you must create a client for your application in the {{book.project.name}} Administration Console. The adapter supports public, confidential and bearer-only access type. Which one to choose depends on the use-case scenario.

Once the client is created click on the `Installation` tab select `{{book.project.name}} OIDC JSON` for `Format Option` then click on `Download`. The downloaded `keycloak.json` file should be at the root folder of your project.

==== Known issue

Node.js adapter requires `realm-public-key` attribute and does not retrieve it automatically from {{book.project.name}}. Otherwise, your Node.js app won't start.

In order to prevent any issues, go to your `Realm Settings` and `Keys`, copy the `Public Key` to your keycloak.json file adding `realm-public-key` attribute like the snippet below:

[source,json]
----
{
  "realm": "example-realm",
  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
  "auth-server-url": "http://localhost:8080/auth",
  "ssl-required": "external",
  "resource": "example-app",
  "credentials": {
    "secret": "mysecret"
  }
}
----

==== Installation

Assuming you've already installed https://nodejs.org[Node.js], create a folder for your application:

    mkdir myapp && cd myapp

Use `npm init` command to create a `package.json` for your application. Now add the {{book.project.name}} connect adapter in the dependencies list:

{% if book.community %}

    dependencies": {
        "keycloak-connect": "{{book.project.versionMvn}}"
    }

{% endif %}

{% if book.product %}

    dependencies": {
        "keycloak-connect": "file://{{book.project.name}}.tgz"
    }

{% endif %}

==== 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.

    var keycloak = new Keycloak();

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
is obtained from the {{book.project.name}} Admin Console.

Instantiation with this method results in all of the reasonable defaults
being used.

Configuring a web session store::

If you wish to use web sessions to manage
server-side state for authentication, you will need to initialize the
`Keycloak(...)` with at least a `store` parameter, passing in the actual
session store that `express-session` is using.

    var session = require('express-session');
    var memoryStore = new session.MemoryStore();

    var keycloak = new Keycloak({ store: memoryStore });

Passing a custom scope value::

By default, the scope value `openid` will be passed as query parameter to {{book.project.name}}'s login URL but you can add an additional custom value :

    var keycloak = new Keycloak({ scope: 'offline_access' });

==== Install middleware

Once instantiated, install the middleware into your connect-capable app:

    var app = express();

    app.use( keycloak.middleware() );

==== Protect resources

Simple authentication::

To enforce that an user must be authenticated before accessing a resource,
simply use a no-argument version of `keycloak.protect()`:

    app.get( '/complain', keycloak.protect(), complaintHandler );

Role-based authorization::

To secure a resource with an application role for the current app:

    app.get( '/special', keycloak.protect('special'), specialHandler );

To secure a resource with an application role for a *different* app:

    app.get( '/extra-special', keycloak.protect('other-app:special', extraSpecialHandler );

To secure a resource with a realm role:

    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:

    function protectBySection(token, request) {
      return token.hasRole( request.params.section );
    }

    app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );

==== Additional URLs

Explicit user-triggered logout::

By default, the middleware catches calls to `/logout` to send the user through a
{{book.project.name}}-centric logout workflow. This can be changed by specifying a `logout`
configuration parameter to the `middleware()` call:

    app.use( keycloak.middleware( { logout: '/logoff' } ));

{{book.project.name}} Admin Callbacks::

Also, the middleware supports callbacks from the {{book.project.name}} console to logout a single
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:

    app.use( keycloak.middleware( { admin: '/callbacks' } );
