From 9a9823e1d8735fe3f1bb612b3405cd64c6a09885 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 11 Aug 2015 15:48:16 -0700 Subject: [PATCH 01/20] split server.md into separate files and add Docker instructions --- server/configure.md | 80 +++++++++++++++ server/getstarted.md | 209 ++++++++++++++++++++++++++++++++++++++ server/logger.md | 20 ++++ server/mailer.md | 61 +++++++++++ server/providers.md | 237 +++++++++++++++++++++++++++++++++++++++++++ server/redis.md | 25 +++++ 6 files changed, 632 insertions(+) create mode 100644 server/configure.md create mode 100644 server/getstarted.md create mode 100644 server/logger.md create mode 100644 server/mailer.md create mode 100644 server/providers.md create mode 100644 server/redis.md diff --git a/server/configure.md b/server/configure.md new file mode 100644 index 0000000..91ee2e6 --- /dev/null +++ b/server/configure.md @@ -0,0 +1,80 @@ +## Configure + +### JSON files + +Anvil Connect loads its configuration from a JSON file in the `config` +directory of the current working directory for the process. File names must +match the `NODE_ENV` value. If `NODE_ENV` is not set, `config/development.json` +will be loaded. + +### Key pairs + +If you generated a deployment repository with `nv init`, a new RSA key pair +will be generated for you in `config/keys`. This pair of files is required for +signing and verifying tokens. We recommend using the generated files. We have +set up key generation to lower the barrier to entry, as it is a tedious, +precise process to do by hand. + +If you want or need to provide your own RSA key pair, you can obtain it using +OpenSSL and import them to the proper location, `config/keys/private.pem` for +the private key and `config/keys/public.pem` for the public key. + +``` +$ cd PROJECT_ROOT +$ mkdir -p config/keys +$ openssl genrsa -out config/keys/private.pem 2048 +$ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem +``` + + +### Server Settings + +##### issuer + +**Type:** string + +**Use:** URI used to identify issuer of authentication + +**Description:** Fully qualified base URI of the authorization server; e.g., https://accounts.anvil.io + + +##### port + +**Type:** integer + +**Use:** port # the Connect server is run under + +**Description:** An integer value representing the port the server will be bound to, unless a PORT environment variable is provided. Defaults to 3000. + +##### cookie_secret + +**Type:** string + +**Use:** signing cookies + +**Description:** A string used for signing cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. + +##### session_secret + +**Type:** string + +**Use:** signing session cookies + +**Description:** A string used for signing session ID cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. + +##### client_registration + +**Type:** string - options: `dynamic`, `token`, or `scoped` + +**Use:** Assigning the type of client registration Connect uses + +**Description:** Anvil Connect can be configured for three types of client registration: `dynamic`, `token`, or `scoped`, each being more restrictive than the previous option. The default `client_registration` type is `scoped`. For more details, see the section titled [Client Registration](#client-registration-1). + +##### trusted_registration_scope + +**Type:** string - options: `realm`, Connect operator's own registered scope(s) + +**Use:** signing session cookies + +**Description:** `trusted_registration_scope` signals if a client is trusted or not - trusted clients require additional scope to register. It defaults to `realm`. + diff --git a/server/getstarted.md b/server/getstarted.md new file mode 100644 index 0000000..910a9cd --- /dev/null +++ b/server/getstarted.md @@ -0,0 +1,209 @@ +## Get Started + +### Requirements + +Anvil Connect works with the latest versions of [Node.js](https://nodejs.org/) (0.12.x) or [io.js](https://iojs.org/en/index.html) and [Redis](http://redis.io/) (3.0.x). + +The server can optionally run inside [Docker](https://www.docker.com/) containers. To run it with Docker or Docker Compose you'll need to have them installed on your system. + + +### Initializing your project + +To get started with Anvil Connect, install the `anvil-connect-cli` package +globally using npm. + +```bash +$ npm install -g anvil-connect-cli +``` + +After this has completed successfully, you can generate all the files you'll +need to run your own custom auth server. First, make a new directory and `cd` +into it. Then, run `nvl init` and answer the prompts. With default options, +this command will generate all the files you need to customize and run Anvil +Connect, with or without Docker, Redis and nginx, depending on your prompt +selections. If you choose to use nginx, you'll also be prompted to create a new +self-signed SSL certificate. You can opt out of any of the components other +than Anvil Connect. + +``` +$ nvl init +? What would you like to name your Connect instance? myconnect +? What (sub)domain will you use? myconnect.example.com +? Would you like to use Docker? Yes +? Would you like to run Redis? Yes +? Would you like to run nginx? Yes +? Would you like to create a self-signed SSL cert? Yes +? Country Name (2 letter code) US +? State or Province Name (full name) South Dakota +? Locality Name (eg, city) Rapid City +? Organization Name (eg, company) Anvil Research, Inc. +``` + +Once finished, you'll have a directory containing all the files needed to run +your auth server. Anvil Connect itself is required as a dependency via npm. +We've structured the package so that you can customize your server without +having to maintain a fork. You can add your own static assets, customize views +(HTML templates), integrate custom auth protocols, manage project-specific +dependencies, and keep all this, along with your configuration files, under +version control. This setup makes upgrading Anvil Connect as simple as changing +the version number in `package.json` in most cases. + + +## Run + +### Running in Docker Containers + +If you've opted to use Docker, Redis, and nginx, you should be ready to roll. +To run a complete, production-ready set of containers you can use Docker +Compose. First, you'll want to ensure a few things. + +#### IP Address + +If you're running on Linux, the IP address Connect will be bound to is +localhost and/or the IP of your computer/server. Once the containers are +running, you should be able to reach the service at `https://0.0.0.0`. + +On Mac and other systems you may need to install boot2docker in order to run +Docker containers locally. Once you've installed boot2docker, you can obtain +the IP address of your local Docker host by running: + +```bash +boot2docker ip +``` + +#### /etc/hosts + +To work with your Anvil Connect instance locally, it's a good idea to make an +entry in your `/etc/hosts` file. For example, on a Mac, you'll want to +associate the (sub)domain you provided the generator with `boot2docker` IP +address. + +```bash +192.168.59.103 connect.example.io +``` + +#### RSA Key Pair + + +#### SSL Certificate + +When you ran `nv init`, you may have opted to generate a self-signed SSL +certificate. The files were created in the `nginx/certs` directory of this +project. If you did not opt to generate these files, you'll need to provide +your own `nginx.key` and `nginx.crt` files. + + +#### Start Anvil Connect + +```bash +$ docker-compose up -d +``` + +#### Stop + +``` +$ docker-compose stop [connect|nginx|redis] +``` + +#### Restart + +``` +$ docker-compose restart +``` + +#### View Logs + +``` +$ docker-compose logs +``` + + +### Building Custom Containers + +By default, Docker Compose is configured to use images provided by Anvil +Research on Docker Hub. You can build images yourself by commenting out the +`image` property of a service in `docker-compose.yml` and uncommenting the +`build` property like so: + +```yaml +connect: + build: connect + #image: anvilresearch/connect + ... +``` + +While we highly recommend using the official images or provided Dockerfiles, +if necessary you can modify them to suit your requirements. You can also push +your own custom images to Docker Hub and use them to run Connect by referencing +them in the `image` property in `docker-compose.yml`. + +```yaml +connect: + #build: connect + image: /connect +``` + +### Running without Docker + +#### Install Dependencies + +Now you can install npm and bower dependencies, if you want to run Connect +locally. + +```bash +$ npm install +$ bower install +``` + +#### Initializing the database + +In current versions of Anvil Connect, database initialization is handled by the +server at run-time. See [Run](#Run) for details. + +`nv migrate` has been deprecated. + +#### Environments + +#### Commands +There are two environments to run the Connect server in, `development`, and +`production`. The development server is for local testing, setup, and +development on Connect itself. The production environment should be used when +deployed to a live environment. + +To run the authorization server in `development` mode, you can run the server +by simply starting it: + +```bash +# The following are equivalent, any of them will start the development server +$ node server.js +$ npm start +``` + +To run the server in production, set `NODE_ENV` to `production`: + +```bash +# The following are equivalent, any of them will start the production server +$ node server.js -e production +$ NODE_ENV=production node server.js +``` + +When Anvil Connect starts for the first time, it will check to see whether or +not the Redis server at the configured hostname and port has any data inside and +whether or not it contains data from a valid Anvil Connect instance. + +If Anvil Connect detects any existing data in the database, and it is not from +an Anvil Connect instance, it will halt with the following error: + +``` +Redis already contains data, but it doesn't seem to be an Anvil Connect database. +If you are SURE it is, start the server with --no-db-check to skip this check. +``` + +If you are sure that there is no conflicting data in Redis, for example, +in the event that you may have edited Redis's data manually, start Anvil Connect +with the `--no-db-check` flag. + +```bash +$ node server.js --no-db-check +``` + diff --git a/server/logger.md b/server/logger.md new file mode 100644 index 0000000..d13c916 --- /dev/null +++ b/server/logger.md @@ -0,0 +1,20 @@ +### Logger + +Anvil Connect uses [bucker](https://github.com/nlf/bucker) for logging. Any valid configuration parameters for bucker can be included in the "logger" parameter in your config file. For example: + +```json +{ + // ... + "logger": { + "console": { + "color": false + }, + "syslog": { + "host": "localhost", + "port": 514, + "facility": 18 + } + } +} +``` + diff --git a/server/mailer.md b/server/mailer.md new file mode 100644 index 0000000..173edc1 --- /dev/null +++ b/server/mailer.md @@ -0,0 +1,61 @@ +### Configuring the mailer + +Anvil Connect uses [nodemailer](https://github.com/andris9/Nodemailer) for sending emails for the purposes of email verification, and other functionality which is to come. + +The configuration file (e.g. development.json, production.json) must have a mailer object on the top level. The options for this configuration object are identical as that of [nodemailer transports](https://github.com/andris9/Nodemailer#use-the-default-smtp-transport), with the exception of an additionally required `from` property. The `from` property defines what e-mail address and name Anvil Connect will use in sending e-mails. It must be in the form `Name `. + +```json +{ + "mailer": { + "from": "Hello World ", + "view_engine": "hogan", + "service": "Gmail", + "auth": { + "user": "test@gmail.com", + "pass": "test" + } + }, +} +``` + +### Configuring e-mail verification + +Anvil Connect supports verifying user e-mail addresses to ensure that the user has ownership/control over their registered address. By default, configuring the mailer will enable email verification server-wide, but not require it. + +When a user signs in or signs up using e-mail/password based authentication, their e-mail address is unverified at first. If the user signs in or signs up using a third-party provider, then Connect will inherit the `email_verified` claim if available. Otherwise, the user's e-mail address stays unverified. + +#### Flow + +1. **Email verification enabled, but not required** + The user is able to sign up for an account with Anvil Connect, and sign in to clients as they normally would, without interruption. However, when the user signs up for the first time, they receive an email asking them to verify their email address. +2. **Email verification enabled and required** + When the user signs up for the first time with an unverified e-mail address, they are redirected to a page that prompts them to check their e-mail for a verification e-mail message. They are also given the option on that page to resend the e-mail in the event that it hasn't made its way through. Until the user verifies their e-mail, they are unable to authenticate with any client. + +#### Configuring verification for the entire server + +```json +{ + "emailVerification": { + "enable": true, + "require": false + }, + ... +} +``` + +#### Configuring verification for specific providers + +```json +{ + "providers": { + "password": { + "emailVerification": { + "enable": true, + "require": false + } + } + } + ... +} +``` + diff --git a/server/providers.md b/server/providers.md new file mode 100644 index 0000000..c400136 --- /dev/null +++ b/server/providers.md @@ -0,0 +1,237 @@ +### Providers + +The providers setting is an object containing settings for various authentication methods. + +```json +{ + // ... + "providers": { ... } +} +``` + +You can see all the natively supported providers in the [providers directory](https://github.com/anvilresearch/connect/tree/master/providers) in the Anvil Connect repository on GitHub. If you want to use an provider not listed there, you can easily add support in your instance by creating a simple configuration file in a providers directory in your project repository. + +#### amr claim + +The `amr` claim is a part of the [OpenID Connect specification][oidcimplicit] +which stands for Authentication Methods References. It determines which methods +of authentication were used during the authentication request. + +For example, if a user signs in with their e-mail and password, then one of the +values of the `amr` claim will be `pwd` for password authentication. If the user +also used two-factor authentication with a disposable token, then the `amr` +claim will be `[ 'mfa', 'pwd', 'otp' ]` for multi-factor authentication, +password authentication, and one-time password. + +Anvil Connect supports taking advantage of the `amr` claim given that it is +defined for a particular provider. You can also configure your own value for the +amr claim for a particular provider in the configuration file. + +We use, and recommend the use of, the [IETF amr values draft][ietfamrvalues] +as a starting point for choosing amr values. + +For example, to define an `amr` value of `ad` for authenticating with Active +Directory: + +```json +{ + // ... + "providers": { + "ActiveDirectory": { + "amr": "ad", + // ... + } + } +} +``` + +#### Password authentication + +To enable password authentication, add a `password` property to the `providers` object with a value of `true`. When set to true, `password` _requires_ login with username/password combination for the given providers every time they sign in. If set to `false`, the user will be able to sign in without authenticating with via username/password with the provider if as they are externally logged into that provider already. + +```json +{ + // ... + "providers": { + "password": true + } +} +``` + +#### OAuth 2.0 + +Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can obtain these by registering your app with the respective provider. + +```json +{ + // ... + "providers": { + "facebook": { + "client_id": "App ID", + "client_secret": "App Secret" + } + } +} +``` + +OAuth 2.0 supports a `scope` authorization parameter, and some providers use it to restricted access to specific resources. You can set scope for a provider using the `scope` property with an array of strings. See provider API documentation for specifics. + +```json +{ + //... + "providers": { + "google": { + "client_id": "Client ID", + "client_secret": "Client secret", + "scope": [ + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email" + ] + }, + "linkedin": { + "client_id": "Client ID", + "client_secret": "Client Secret", + "scope": [ + "r_basicprofile", + "r_fullprofile", + "r_emailaddress", + "r_network", + "r_contactinfo" + ] + } + } +} +``` + +#### OAuth 1.0 + +OAuth 1.0 providers require `oauth_consumer_key` and `oauth_consumer_secret`. + + +```json +{ + //... + "providers": { + "twitter": { + "oauth_consumer_key": "Consumer Key (API Key)", + "oauth_consumer_secret": "Consumer Secret" + } + } +} +``` +#### LDAP + +Because of LDAP's flexible nature, LDAP support is provided in the form of a +provider template which can be used to handle custom LDAP attribute to OpenID +Connect claim scenarios. A basic provider that inherits this template without +modification is provided for convenience. + +LDAP providers can be configured as follows: + +```json +{ + // ... + "providers": { + "LDAP": { + "url": "ldap://corp.example.com", + "bindDn": "cn=admin,dc=example,dc=com", + "bindCredentials": "pass1234", + "searchBase": "ou=people,dc=example,dc=com", + "searchFilter": "(cn={{username}})" + } + } +} +``` + +A [full list of configuration options][passport-ldapauth-config] is available +from the passport-ldapauth library. + +By default, LDAP attributes map to OpenID Connect claims as such: + +OpenID Connect claim | LDAP attribute +-------------------- | -------------- +id | dn +email | mail +name | cn +given\_name | givenName +family\_name | sn +phone\_number | telephoneNumber +address.formatted | postalAddress +address.street\_address | street +address.locality | l +address.region | st +address.postal\_code | postalCode +address.country | co + +To customize these mappings, simply create your own provider in the `providers` +folder of your Anvil Connect instance. For example: + +```js +module.exports = function(config) { + return { + id: 'MyLDAP', + name: 'Example Corp.', + templates: [ 'LDAP' ], + mapping: { + id: 'uid', + name: 'displayName' + }; +}; +``` + + +##### Active Directory + +The expected configuration format for the Active Directory provider is as follows: + +```json +{ + ... + "providers": { + "ActiveDirectory": { + "url": "ldaps://corp.example.com", + "domainDn": "dc=example,dc=com", + "tlsOptions": { + "ca": "/path/to/the/self/signed/ca-cert.cer" + } + } + } +} +``` + +Anvil Connect also provides the `ActiveDirectory` provider template in the event that you may be working with several domains at a time or if you would like to customize certain aspects of the AD provider, such as the name. + +Here's an example provider that uses the template: + +```javascript +module.exports = function(config) { + return { + id: 'examplecorpad', + name: 'Example Corporation', + templates: [ 'ActiveDirectory' ] + }; +}; +``` + +To configure this provider, you would use `examplecorpad` in place of `ActiveDirectory` in your configuration. + +```json +{ + ... + "providers": { + "examplecorpad": { ... } + } +} +``` + + +##### Groups + +The LDAP provider will synchronize the user's role membership in Anvil Connect with their group membership in the domain. In order to take advantage of this feature, each LDAP group for which you wish to enable synchronization must have a respective role in Connect named after the fully-qualified distinguished name (FQDN) of the group in the directory. + +For example, if there exists a group in the directory service with FQDN `CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the user's role membership if there also exists a role in Connect named `CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the `nv add role` command: + +```bash +nv add role '{ "name": "CN=Group 1,OU=Groups,DC=example,DC=com" }' +``` + diff --git a/server/redis.md b/server/redis.md new file mode 100644 index 0000000..323039a --- /dev/null +++ b/server/redis.md @@ -0,0 +1,25 @@ +### Redis + +Anvil Connect requires access to a Redis database and uses the default host and port for a local instance. To use a remote Redis server, provide url and auth parameters under the "redis" object in your config. + +```json +{ + // ... + "redis": { + "url": "redis://HOST:PORT", + "auth": "PASSWORD" + } +} +``` + +You can also provide a `db` setting (integer) if you want to use a different Redis database. By default, Redis is configured to support 16 databases (0 - 15). This can be configured in the `redis.conf` file for your Redis installation. + +```json +{ + // ... + "redis": { + "db": 3 + } +} +``` + From 8e31f18c85a964b3df7c0c63a3ac1a61907aa932 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Wed, 12 Aug 2015 16:17:54 -0700 Subject: [PATCH 02/20] draft protocols and providers documentation --- server/protocols.md | 211 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 server/protocols.md diff --git a/server/protocols.md b/server/protocols.md new file mode 100644 index 0000000..4d54267 --- /dev/null +++ b/server/protocols.md @@ -0,0 +1,211 @@ +## User Authentication + +Out of the box, Anvil Connect supports authenticating users with local +passwords, OAuth 1.0, OAuth 2.0, OpenID, LDAP, and ActiveDirectory. We call +these authentication methods "protocols". + +A "provider" is a specific service providing authentication by means of a given +protocol. For example, Facebook, GitHub, and Dropbox are OAuth 2.0 providers. +They implement OAuth 2.0, and that's the protocol we use to interface with them +in the auth server. + +For each supported protocol, we implement a module that supports any compliant +provider. This way, there's no need to write OAuth 2.0 code to support a new +OAuth 2.0-based service. Within Anvil Connect, providers and protocols work +together to separate the differences between authentication methods from the +parts that remain the same. + +In addition to what we ship with Anvil Connect, it only takes a small amount of +code in your project to authenticate using virtually any other method. You can +customize your Connect instance to use additional providers and protocols by +creating special directories in your project and adding some JavaScript. + + + +### Adding Providers + +To add a new provider, create a `connect/providers` directory in your Anvil +Connect project and add a file named for the provider. The filename (not +including the .js extension) must be a valid JSON key since you'll be using it +in your configuration file. Let's say we want to add an OAuth 2.0 provider for +GitHub (although this provider is already supported). We'll create a file +called `connect/providers/github.js`. It should export a function that takes a +`config` argument which contains all settings for the server. + +``` +/** + * GitHub + */ + +module.exports = function (config) { + return { + id: 'github', + name: 'GitHub', + protocol: 'OAuth2', + // ... + // protocol specific properties + // ... + mapping: { + id: 'id', + email: 'email', + name: 'name', + website: 'blog', + preferredUsername: 'login', + profile: 'html_url', + picture: 'avatar_url', + } + }; +}; +``` + +When invoked, this function returns a simple JavaScript object containing all +the parameters needed by the corresponding protocol. + +#### id Property + +The `id` property is used by the server to match a provider-specific +authorization request to this provider metadata. A good heuristic is to name +it the same as the filename (without the `.js` extension). + +#### Protocol Property + +The `protocol` property corresponds to the file name (sans extension) of the +protocol module you wish to use. Built in protocols you may wish to add a +provider for include `OAuth`, `OAuth2`, `OpenID`, `LDAP`, and +`ActiveDirectory`. If you add a [custom protocol](#?), use the basename of the +file for this value. + +#### Mapping Property + +The `mapping` property determines how user info from the provider gets mapped +into the OpenID Connect claims stored for each user inside Anvil Connect. On +the left are Anvil Connect user properties and on the right are property names +from the provider. You can reference nested properties using dot notation. +Given an object `{ info: { emails: { home: "foo@example.com" } } }`, your +mapping would contain `email: 'info.emails.home'`. The value side of a mapping +can also be a function, where the argument is the entire user info object from +the provider. + + +#### OAuth 2.0 Providers + + +``` +/** + * GitHub + */ + +module.exports = function (config) { + return { + id: 'github', + name: 'GitHub', + protocol: 'OAuth2', + url: 'https://github.com', + redirect_uri: config.issuer + '/connect/github/callback', + endpoints: { + authorize: { + url: 'https://github.com/login/oauth/authorize', + method: 'POST', + }, + token: { + url: 'https://github.com/login/oauth/access_token', + method: 'POST', + auth: 'client_secret_post' + }, + user: { + url: 'https://api.github.com/user', + method: 'GET', + auth: { + header: 'Authorization', + scheme: 'Bearer' + } + } + }, + separator: ',', + mapping: { + id: 'id', + email: 'email', + name: 'name', + website: 'blog', + preferredUsername: 'login', + profile: 'html_url', + picture: 'avatar_url', + } + }; +}; +``` + + +#### OAuth 1.0 Providers + +#### LDAP Providers + +#### Active Directory Providers + +#### OpenID Providers + + +#### Contributing commonly used providers + +Contributing new OAuth and OAuth 2.0 providers is one of the easiest ways to +get involved with the open source project. While many custom providers may not +be suitable for inclusion in the core of Anvil Connect, we really appreciate +pull requests for those that are. + + + + +### Adding Protocols + +To add a new protocol, create a `connect/protocols` directory in your Anvil +Connect project and add a JavaScript file named for the protocol. The filename +should be a camel cased string. + +This new module should export a Passport strategy that has two extra functions +appended to it: `verifier` and `initialize`. You can use any virtually existing +Passport strategy as a starting point, or write your own from scratch. + + +```javascript +/** + * Dependencies + */ + +var Strategy = require('passport-ANYTHING').Strategy; + + +/** + * Verifier + */ + +function verifier (req, [?..,] done) { + // ... +}; + +Strategy.verifier = verifier; + + +/** + * Initialize + */ + +function initialize (provider, configuration) { + return new Strategy([...], verifier); +} + +Strategy.initialize = initialize; + + +/** + * Export + */ + +module.exports = strategy; +``` + +The verifier function is the callback that get's invoked by Passport once +authentication has completed. + +#### Verifier + +#### Initialize From 2bc03b29bf606207b4767763c026440fbb7976f6 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Sun, 23 Aug 2015 15:18:48 -0700 Subject: [PATCH 03/20] format to 80 character width --- server/configure.md | 26 ++++++++++++++++++------ server/getstarted.md | 8 +++++--- server/logger.md | 4 +++- server/mailer.md | 31 ++++++++++++++++++++++------ server/providers.md | 48 ++++++++++++++++++++++++++++++++++---------- server/redis.md | 9 +++++++-- 6 files changed, 97 insertions(+), 29 deletions(-) diff --git a/server/configure.md b/server/configure.md index 91ee2e6..fa66475 100644 --- a/server/configure.md +++ b/server/configure.md @@ -35,7 +35,8 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** URI used to identify issuer of authentication -**Description:** Fully qualified base URI of the authorization server; e.g., https://accounts.anvil.io +**Description:** Fully qualified base URI of the authorization server; e.g., +https://accounts.anvil.io ##### port @@ -44,7 +45,9 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** port # the Connect server is run under -**Description:** An integer value representing the port the server will be bound to, unless a PORT environment variable is provided. Defaults to 3000. +**Description:** An integer value representing the port the server will be bound +to, unless a PORT environment variable is provided. Defaults to +3000. ##### cookie_secret @@ -52,7 +55,9 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** signing cookies -**Description:** A string used for signing cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. +**Description:** A string used for signing cookies. When you initialize a +project, this value is generated for each of your environments. Treat it as +confidential and always use separate values for each project and environment. ##### session_secret @@ -60,7 +65,10 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** signing session cookies -**Description:** A string used for signing session ID cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. +**Description:** A string used for signing session ID cookies. When you +initialize a project, this value is generated for each of your environments. +Treat it as confidential and always use separate values for each project and +environment. ##### client_registration @@ -68,7 +76,11 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** Assigning the type of client registration Connect uses -**Description:** Anvil Connect can be configured for three types of client registration: `dynamic`, `token`, or `scoped`, each being more restrictive than the previous option. The default `client_registration` type is `scoped`. For more details, see the section titled [Client Registration](#client-registration-1). +**Description:** Anvil Connect can be configured for three types of client +registration: `dynamic`, `token`, or `scoped`, each being more restrictive than +the previous option. The default `client_registration` type is `scoped`. For +more details, see the section titled +[Client Registration](#client-registration-1). ##### trusted_registration_scope @@ -76,5 +88,7 @@ $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem **Use:** signing session cookies -**Description:** `trusted_registration_scope` signals if a client is trusted or not - trusted clients require additional scope to register. It defaults to `realm`. +**Description:** `trusted_registration_scope` signals if a client is trusted or +not - trusted clients require additional scope to register. It defaults to +`realm`. diff --git a/server/getstarted.md b/server/getstarted.md index 910a9cd..27124c0 100644 --- a/server/getstarted.md +++ b/server/getstarted.md @@ -2,9 +2,11 @@ ### Requirements -Anvil Connect works with the latest versions of [Node.js](https://nodejs.org/) (0.12.x) or [io.js](https://iojs.org/en/index.html) and [Redis](http://redis.io/) (3.0.x). - -The server can optionally run inside [Docker](https://www.docker.com/) containers. To run it with Docker or Docker Compose you'll need to have them installed on your system. +Anvil Connect works with the latest versions of [Node.js](https://nodejs.org/) +(0.12.x) or [io.js](https://iojs.org/en/index.html) and +[Redis](http://redis.io/) (3.0.x). The server can optionally run inside +[Docker](https://www.docker.com/) containers. To run it with Docker or Docker +Compose you'll need to have them installed on your system. ### Initializing your project diff --git a/server/logger.md b/server/logger.md index d13c916..05f05c0 100644 --- a/server/logger.md +++ b/server/logger.md @@ -1,6 +1,8 @@ ### Logger -Anvil Connect uses [bucker](https://github.com/nlf/bucker) for logging. Any valid configuration parameters for bucker can be included in the "logger" parameter in your config file. For example: +Anvil Connect uses [bucker](https://github.com/nlf/bucker) for logging. Any +valid configuration parameters for bucker can be included in the "logger" +parameter in your config file. For example: ```json { diff --git a/server/mailer.md b/server/mailer.md index 173edc1..b950bac 100644 --- a/server/mailer.md +++ b/server/mailer.md @@ -1,8 +1,15 @@ ### Configuring the mailer -Anvil Connect uses [nodemailer](https://github.com/andris9/Nodemailer) for sending emails for the purposes of email verification, and other functionality which is to come. +Anvil Connect uses [nodemailer](https://github.com/andris9/Nodemailer) for +sending emails for the purposes of email verification, and other functionality +which is to come. -The configuration file (e.g. development.json, production.json) must have a mailer object on the top level. The options for this configuration object are identical as that of [nodemailer transports](https://github.com/andris9/Nodemailer#use-the-default-smtp-transport), with the exception of an additionally required `from` property. The `from` property defines what e-mail address and name Anvil Connect will use in sending e-mails. It must be in the form `Name `. +The configuration file (e.g. development.json, production.json) must have a +mailer object on the top level. The options for this configuration object are +identical as that of [nodemailer transports](https://github.com/andris9/Nodemailer#use-the-default-smtp-transport), +with the exception of an additionally required `from` property. The `from` +property defines what e-mail address and name Anvil Connect will use in sending +e-mails. It must be in the form `Name `. ```json { @@ -20,16 +27,28 @@ The configuration file (e.g. development.json, production.json) must have a mail ### Configuring e-mail verification -Anvil Connect supports verifying user e-mail addresses to ensure that the user has ownership/control over their registered address. By default, configuring the mailer will enable email verification server-wide, but not require it. +Anvil Connect supports verifying user e-mail addresses to ensure that the user +has ownership/control over their registered address. By default, configuring the +mailer will enable email verification server-wide, but not require it. -When a user signs in or signs up using e-mail/password based authentication, their e-mail address is unverified at first. If the user signs in or signs up using a third-party provider, then Connect will inherit the `email_verified` claim if available. Otherwise, the user's e-mail address stays unverified. +When a user signs in or signs up using e-mail/password based authentication, +their e-mail address is unverified at first. If the user signs in or signs up +using a third-party provider, then Connect will inherit the `email_verified` +claim if available. Otherwise, the user's e-mail address stays unverified. #### Flow 1. **Email verification enabled, but not required** - The user is able to sign up for an account with Anvil Connect, and sign in to clients as they normally would, without interruption. However, when the user signs up for the first time, they receive an email asking them to verify their email address. + The user is able to sign up for an account with Anvil Connect, and sign in + to clients as they normally would, without interruption. However, when the + user signs up for the first time, they receive an email asking them to verify + their email address. 2. **Email verification enabled and required** - When the user signs up for the first time with an unverified e-mail address, they are redirected to a page that prompts them to check their e-mail for a verification e-mail message. They are also given the option on that page to resend the e-mail in the event that it hasn't made its way through. Until the user verifies their e-mail, they are unable to authenticate with any client. + When the user signs up for the first time with an unverified e-mail address, + they are redirected to a page that prompts them to check their e-mail for a + verification e-mail message. They are also given the option on that page to + resend the e-mail in the event that it hasn't made its way through. Until the + user verifies their e-mail, they are unable to authenticate with any client. #### Configuring verification for the entire server diff --git a/server/providers.md b/server/providers.md index c400136..808e8d2 100644 --- a/server/providers.md +++ b/server/providers.md @@ -1,6 +1,7 @@ ### Providers -The providers setting is an object containing settings for various authentication methods. +The providers setting is an object containing settings for various +authentication methods. ```json { @@ -9,7 +10,11 @@ The providers setting is an object containing settings for various authenticatio } ``` -You can see all the natively supported providers in the [providers directory](https://github.com/anvilresearch/connect/tree/master/providers) in the Anvil Connect repository on GitHub. If you want to use an provider not listed there, you can easily add support in your instance by creating a simple configuration file in a providers directory in your project repository. +You can see all the natively supported providers in the +[providers directory](https://github.com/anvilresearch/connect/tree/master/providers) +in the Anvil Connect repository on GitHub. If you want to use an provider not +listed there, you can easily add support in your instance by creating a simple +configuration file in a providers directory in your project repository. #### amr claim @@ -47,7 +52,12 @@ Directory: #### Password authentication -To enable password authentication, add a `password` property to the `providers` object with a value of `true`. When set to true, `password` _requires_ login with username/password combination for the given providers every time they sign in. If set to `false`, the user will be able to sign in without authenticating with via username/password with the provider if as they are externally logged into that provider already. +To enable password authentication, add a `password` property to the `providers` +object with a value of `true`. When set to true, `password` _requires_ login +with username/password combination for the given providers every time they sign +in. If set to `false`, the user will be able to sign in without authenticating +with via username/password with the provider if as they are externally logged +into that provider already. ```json { @@ -60,7 +70,8 @@ To enable password authentication, add a `password` property to the `providers` #### OAuth 2.0 -Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can obtain these by registering your app with the respective provider. +Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can +obtain these by registering your app with the respective provider. ```json { @@ -74,7 +85,10 @@ Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can } ``` -OAuth 2.0 supports a `scope` authorization parameter, and some providers use it to restricted access to specific resources. You can set scope for a provider using the `scope` property with an array of strings. See provider API documentation for specifics. +OAuth 2.0 supports a `scope` authorization parameter, and some providers use it +to restricted access to specific resources. You can set scope for a provider +using the `scope` property with an array of strings. See provider API +documentation for specifics. ```json { @@ -182,7 +196,8 @@ module.exports = function(config) { ##### Active Directory -The expected configuration format for the Active Directory provider is as follows: +The expected configuration format for the Active Directory provider is as +follows: ```json { @@ -199,7 +214,9 @@ The expected configuration format for the Active Directory provider is as follow } ``` -Anvil Connect also provides the `ActiveDirectory` provider template in the event that you may be working with several domains at a time or if you would like to customize certain aspects of the AD provider, such as the name. +Anvil Connect also provides the `ActiveDirectory` provider template in the event +that you may be working with several domains at a time or if you would like to +customize certain aspects of the AD provider, such as the name. Here's an example provider that uses the template: @@ -213,7 +230,8 @@ module.exports = function(config) { }; ``` -To configure this provider, you would use `examplecorpad` in place of `ActiveDirectory` in your configuration. +To configure this provider, you would use `examplecorpad` in place of +`ActiveDirectory` in your configuration. ```json { @@ -227,9 +245,17 @@ To configure this provider, you would use `examplecorpad` in place of `ActiveDir ##### Groups -The LDAP provider will synchronize the user's role membership in Anvil Connect with their group membership in the domain. In order to take advantage of this feature, each LDAP group for which you wish to enable synchronization must have a respective role in Connect named after the fully-qualified distinguished name (FQDN) of the group in the directory. - -For example, if there exists a group in the directory service with FQDN `CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the user's role membership if there also exists a role in Connect named `CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the `nv add role` command: +The LDAP provider will synchronize the user's role membership in Anvil Connect +with their group membership in the domain. In order to take advantage of this +feature, each LDAP group for which you wish to enable synchronization must have +a respective role in Connect named after the fully-qualified distinguished name +(FQDN) of the group in the directory. + +For example, if there exists a group in the directory service with FQDN +`CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the +user's role membership if there also exists a role in Connect named +`CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the +`nv add role` command: ```bash nv add role '{ "name": "CN=Group 1,OU=Groups,DC=example,DC=com" }' diff --git a/server/redis.md b/server/redis.md index 323039a..97ff321 100644 --- a/server/redis.md +++ b/server/redis.md @@ -1,6 +1,8 @@ ### Redis -Anvil Connect requires access to a Redis database and uses the default host and port for a local instance. To use a remote Redis server, provide url and auth parameters under the "redis" object in your config. +Anvil Connect requires access to a Redis database and uses the default host and +port for a local instance. To use a remote Redis server, provide url and auth +parameters under the "redis" object in your config. ```json { @@ -12,7 +14,10 @@ Anvil Connect requires access to a Redis database and uses the default host and } ``` -You can also provide a `db` setting (integer) if you want to use a different Redis database. By default, Redis is configured to support 16 databases (0 - 15). This can be configured in the `redis.conf` file for your Redis installation. +You can also provide a `db` setting (integer) if you want to use a different +Redis database. By default, Redis is configured to support 16 databases +(0 - 15). This can be configured in the `redis.conf` file for your Redis +installation. ```json { From 1e6b81b9b1c8b94bb4cd50634d3afea3f1bd74bb Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Mon, 24 Aug 2015 15:28:54 -0700 Subject: [PATCH 04/20] rewrite instructions for running locally and various other improvements --- server/getstarted.md | 231 +++++++++++++++++++++++++------------------ 1 file changed, 134 insertions(+), 97 deletions(-) diff --git a/server/getstarted.md b/server/getstarted.md index 27124c0..7028324 100644 --- a/server/getstarted.md +++ b/server/getstarted.md @@ -2,11 +2,26 @@ ### Requirements -Anvil Connect works with the latest versions of [Node.js](https://nodejs.org/) -(0.12.x) or [io.js](https://iojs.org/en/index.html) and -[Redis](http://redis.io/) (3.0.x). The server can optionally run inside -[Docker](https://www.docker.com/) containers. To run it with Docker or Docker -Compose you'll need to have them installed on your system. +Anvil Connect works with the latest versions of [Node.js][nodejs] (0.12.x) or +[io.js][iojs] (3.x.x) and [Redis][redis] (3.0.x) and is tested on +[Debian][debian], [Unbuntu][ubuntu], [Alpine][alpine] Linux distributions, and +Mac OS X. + +The server and its dependencies can optionally run inside [Docker][docker] +containers. We recommend using Docker Compose, although it is not required. +[Installation instructions][docker-install] for Docker and related tools are +available on the Docker website. On Mac and Windows you can easily set up a +Docker environment using the [Docker Toolbox][docker-toolbox]. + +[nodejs]: https://nodejs.org +[iojs]: https://iojs.org +[redis]: http://redis.io +[debian]: https://www.debian.org +[ubuntu]: http://www.ubuntu.com +[alpine]: https://www.alpinelinux.org +[docker]: https://www.docker.com +[docker-install]: https://docs.docker.com/installation +[docker-toolbox]: https://www.docker.com/toolbox ### Initializing your project @@ -19,58 +34,142 @@ $ npm install -g anvil-connect-cli ``` After this has completed successfully, you can generate all the files you'll -need to run your own custom auth server. First, make a new directory and `cd` -into it. Then, run `nvl init` and answer the prompts. With default options, -this command will generate all the files you need to customize and run Anvil -Connect, with or without Docker, Redis and nginx, depending on your prompt -selections. If you choose to use nginx, you'll also be prompted to create a new -self-signed SSL certificate. You can opt out of any of the components other -than Anvil Connect. +need to run your own custom auth server. + +First, make a new directory and `cd` into it. Then, run `nvl init`. ``` +$ mkdir myauthserver +$ cd myauthserver $ nvl init -? What would you like to name your Connect instance? myconnect -? What (sub)domain will you use? myconnect.example.com +``` + +This command will prompt you for some essential information and choices about +your deployment. + +With default options, this command will generate all the files you +need to customize and run Anvil Connect, with or without Docker, Redis and +nginx, depending on your prompt selections. + +If you choose to use nginx, you'll also be prompted to create a new self-signed +SSL certificate. You can opt out of any of the components other than Anvil +Connect. + +```bash +# defaults to the name of the current directory +? What would you like to name your Connect instance? + +# FQDN of the auth server +# This can be localhost, an IP address, or a (sub)domain +? What (sub)domain will you use? connect.example.io + +# We recommend our default Docker setup, including +# support for running Anvil Connect, Redis, and nginx +# with Docker Compose. You can opt out of any or all +# of this if Docker isn't your cup of tea. ? Would you like to use Docker? Yes + +# We can generate a Redis configuration and optional +# Dockerfile. You can also configure Anvil Connect to +# run against any Redis instance available over the +# network. ? Would you like to run Redis? Yes + +# We recommend using nginx for SSL termination, load balancing, +# and caching of static assets. If you wish to employ other means +# answer "no". ? Would you like to run nginx? Yes + +# With nginx or without it, be sure to use SSL in production ? Would you like to create a self-signed SSL cert? Yes + +# If you opt "yes" to generating an SSL cert, you'll be +# prompted for the certificate subject information. ? Country Name (2 letter code) US ? State or Province Name (full name) South Dakota ? Locality Name (eg, city) Rapid City -? Organization Name (eg, company) Anvil Research, Inc. +? Organization Name (eg, company) Anvil Research, Inc ``` Once finished, you'll have a directory containing all the files needed to run -your auth server. Anvil Connect itself is required as a dependency via npm. +your auth server. + We've structured the package so that you can customize your server without having to maintain a fork. You can add your own static assets, customize views (HTML templates), integrate custom auth protocols, manage project-specific dependencies, and keep all this, along with your configuration files, under -version control. This setup makes upgrading Anvil Connect as simple as changing -the version number in `package.json` in most cases. +version control using git. This setup makes upgrading Anvil Connect as simple +as changing the version number in `connect/package.json` in most cases. ## Run +### Running locally + +A Redis instance needs to running locally or accessible over the network. Before you +can run Anvil Connect, you'll also need to install npm and bower dependencies. + +```bash +$ cd connect +$ npm install +$ bower install +``` + +You can run the server in `development` mode with: + +```bash +$ node server.js +``` + +This will use the `config/development.json` settings. To run in production mode, set +the `NODE_ENV` environment variable to `production`. + +```bash +$ NODE_ENV=production node server.js +``` + +When Anvil Connect starts for the first time, it will check to see whether or +not the Redis server at the configured hostname and port has any data inside and +whether or not it contains data from a valid Anvil Connect instance. + +If Anvil Connect detects any existing data in the database, and it is not from +an Anvil Connect instance, it will halt with the following error: + +``` +Redis already contains data, but it doesn't seem to be an Anvil Connect database. +If you are SURE it is, start the server with --no-db-check to skip this check. +``` + +If you are sure that there is no conflicting data in Redis, for example, +in the event that you may have edited Redis's data manually, start Anvil Connect +with the `--no-db-check` flag. + +```bash +$ node server.js --no-db-check +``` + + + ### Running in Docker Containers If you've opted to use Docker, Redis, and nginx, you should be ready to roll. -To run a complete, production-ready set of containers you can use Docker -Compose. First, you'll want to ensure a few things. +You can use Docker Compose to run a complete, production-ready set of +containers. + +First, you'll want to ensure a few things are in order. #### IP Address -If you're running on Linux, the IP address Connect will be bound to is -localhost and/or the IP of your computer/server. Once the containers are -running, you should be able to reach the service at `https://0.0.0.0`. +If you're running on Linux, Anvil Connect will be bound to localhost and/or the +IP of your computer/server. Once the containers are running, you should be able +to reach the service at `https://0.0.0.0`. + -On Mac and other systems you may need to install boot2docker in order to run -Docker containers locally. Once you've installed boot2docker, you can obtain -the IP address of your local Docker host by running: +On Mac once you've installed the [Docker Toolbox][docker-toolbox] you can get +the IP address with the following command. ```bash -boot2docker ip +$ docker-machine ip default ``` #### /etc/hosts @@ -81,21 +180,20 @@ associate the (sub)domain you provided the generator with `boot2docker` IP address. ```bash -192.168.59.103 connect.example.io +192.168.99.100 connect.example.io ``` -#### RSA Key Pair - - #### SSL Certificate When you ran `nv init`, you may have opted to generate a self-signed SSL certificate. The files were created in the `nginx/certs` directory of this project. If you did not opt to generate these files, you'll need to provide -your own `nginx.key` and `nginx.crt` files. +your own `nginx.key` and `nginx.crt` files in the `nginx/certs` directory. + +#### Start Anvil Connect with Docker Compose -#### Start Anvil Connect +You can run these commands in the directory where you ran `nvl init`. ```bash $ docker-compose up -d @@ -115,6 +213,9 @@ $ docker-compose restart #### View Logs +If you're having trouble reaching the running Anvil Connect instance, you can +view the logs for each type of container with the following command. + ``` $ docker-compose logs ``` @@ -145,67 +246,3 @@ connect: image: /connect ``` -### Running without Docker - -#### Install Dependencies - -Now you can install npm and bower dependencies, if you want to run Connect -locally. - -```bash -$ npm install -$ bower install -``` - -#### Initializing the database - -In current versions of Anvil Connect, database initialization is handled by the -server at run-time. See [Run](#Run) for details. - -`nv migrate` has been deprecated. - -#### Environments - -#### Commands -There are two environments to run the Connect server in, `development`, and -`production`. The development server is for local testing, setup, and -development on Connect itself. The production environment should be used when -deployed to a live environment. - -To run the authorization server in `development` mode, you can run the server -by simply starting it: - -```bash -# The following are equivalent, any of them will start the development server -$ node server.js -$ npm start -``` - -To run the server in production, set `NODE_ENV` to `production`: - -```bash -# The following are equivalent, any of them will start the production server -$ node server.js -e production -$ NODE_ENV=production node server.js -``` - -When Anvil Connect starts for the first time, it will check to see whether or -not the Redis server at the configured hostname and port has any data inside and -whether or not it contains data from a valid Anvil Connect instance. - -If Anvil Connect detects any existing data in the database, and it is not from -an Anvil Connect instance, it will halt with the following error: - -``` -Redis already contains data, but it doesn't seem to be an Anvil Connect database. -If you are SURE it is, start the server with --no-db-check to skip this check. -``` - -If you are sure that there is no conflicting data in Redis, for example, -in the event that you may have edited Redis's data manually, start Anvil Connect -with the `--no-db-check` flag. - -```bash -$ node server.js --no-db-check -``` - From 5225d17081f0ebfe6227846b1366cd6192501dda Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Mon, 24 Aug 2015 15:46:09 -0700 Subject: [PATCH 05/20] Tabularize server settings --- server/configure.md | 72 +++++---------------------------------------- 1 file changed, 8 insertions(+), 64 deletions(-) diff --git a/server/configure.md b/server/configure.md index fa66475..52cdc86 100644 --- a/server/configure.md +++ b/server/configure.md @@ -26,69 +26,13 @@ $ openssl genrsa -out config/keys/private.pem 2048 $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem ``` - ### Server Settings -##### issuer - -**Type:** string - -**Use:** URI used to identify issuer of authentication - -**Description:** Fully qualified base URI of the authorization server; e.g., -https://accounts.anvil.io - - -##### port - -**Type:** integer - -**Use:** port # the Connect server is run under - -**Description:** An integer value representing the port the server will be bound -to, unless a PORT environment variable is provided. Defaults to -3000. - -##### cookie_secret - -**Type:** string - -**Use:** signing cookies - -**Description:** A string used for signing cookies. When you initialize a -project, this value is generated for each of your environments. Treat it as -confidential and always use separate values for each project and environment. - -##### session_secret - -**Type:** string - -**Use:** signing session cookies - -**Description:** A string used for signing session ID cookies. When you -initialize a project, this value is generated for each of your environments. -Treat it as confidential and always use separate values for each project and -environment. - -##### client_registration - -**Type:** string - options: `dynamic`, `token`, or `scoped` - -**Use:** Assigning the type of client registration Connect uses - -**Description:** Anvil Connect can be configured for three types of client -registration: `dynamic`, `token`, or `scoped`, each being more restrictive than -the previous option. The default `client_registration` type is `scoped`. For -more details, see the section titled -[Client Registration](#client-registration-1). - -##### trusted_registration_scope - -**Type:** string - options: `realm`, Connect operator's own registered scope(s) - -**Use:** signing session cookies - -**Description:** `trusted_registration_scope` signals if a client is trusted or -not - trusted clients require additional scope to register. It defaults to -`realm`. - +Setting | Type | Default | Description +------- | ---- | ------- | ----------- +**issuer** | string | (none) | URI used to identify issuer of authentication +**port** | integer | 3000 | Port the Connect server is bound to +**cookie_secret** | string | (generated) | Secret string used to sign secure cookies +**session_secret** | string | (generated) | Secret string used to sign session ID cookies +**client_registration** | string | `scoped` | Type of client registration - `dynamic`, `token`, or `scoped` ([Explanation](../clients.md#registration)) +**trusted_registration_scope** | string | `realm` | Scope used to identify trusted clients. From c33bbbe1782e23a4fcf2f46dde29e4ad75a76725 Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Mon, 24 Aug 2015 15:48:08 -0700 Subject: [PATCH 06/20] Fix formatting in mailer flow section --- server/mailer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/mailer.md b/server/mailer.md index b950bac..cac60ad 100644 --- a/server/mailer.md +++ b/server/mailer.md @@ -38,12 +38,12 @@ claim if available. Otherwise, the user's e-mail address stays unverified. #### Flow -1. **Email verification enabled, but not required** +1. **Email verification enabled, but not required** The user is able to sign up for an account with Anvil Connect, and sign in to clients as they normally would, without interruption. However, when the user signs up for the first time, they receive an email asking them to verify their email address. -2. **Email verification enabled and required** +2. **Email verification enabled and required** When the user signs up for the first time with an unverified e-mail address, they are redirected to a page that prompts them to check their e-mail for a verification e-mail message. They are also given the option on that page to From 96d416e490d792b15188fe15cd22d31a1aecbcd3 Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Mon, 24 Aug 2015 16:18:24 -0700 Subject: [PATCH 07/20] Remove augment.md --- augment.md | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 augment.md diff --git a/augment.md b/augment.md deleted file mode 100644 index 74e95fb..0000000 --- a/augment.md +++ /dev/null @@ -1,12 +0,0 @@ -# Connect Augment -We'd like to support every language, every platform, and every application there is in the world. Unfortunately, that's not something that happens overnight. - -Below is a list of the pieces of software the Connect community wants to support as soon as possible. If there's one you'd like Connect to support, send a PR adding it to the list, and it will be registered as a priority for integration. - - From f5c79e6f7f9319ed0a93908fdac7a38bb31c22b7 Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Mon, 24 Aug 2015 17:45:22 -0700 Subject: [PATCH 08/20] Re-organize folder structure --- README.md | 2 + clients.md | 70 +++ server/getstarted.md => getting-started.md | 2 +- permissions.md | 72 --- protocols.md | 72 +++ providers/LDAP.md | 128 +++++ providers/OAuth.md | 16 + providers/OAuth2.md | 96 ++++ providers/Password.md | 17 + providers/README.md | 88 +++ server.md | 610 --------------------- server/{configure.md => configuration.md} | 30 +- server/protocols.md | 211 ------- server/providers.md | 263 --------- 14 files changed, 507 insertions(+), 1170 deletions(-) rename server/getstarted.md => getting-started.md (99%) create mode 100644 protocols.md create mode 100644 providers/LDAP.md create mode 100644 providers/OAuth.md create mode 100644 providers/OAuth2.md create mode 100644 providers/Password.md create mode 100644 providers/README.md delete mode 100644 server.md rename server/{configure.md => configuration.md} (92%) delete mode 100644 server/protocols.md delete mode 100644 server/providers.md diff --git a/README.md b/README.md index 3c30d11..8f1f7e1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ This is the official documentation for [Anvil Connect](https://github.com/anvilresearch/connect) and related projects. +## [Getting started](getting-started.md) + ## Support ### Chat with us diff --git a/clients.md b/clients.md index 82fc86a..4f8c40f 100644 --- a/clients.md +++ b/clients.md @@ -96,6 +96,76 @@ content-type: application/json ### REST API +### Registration permissions + +Anvil Connect can be configured for three types of client registration: `dynamic`, `token`, or `scoped`, each being more restrictive than the previous option. The default `client_registration` type is `scoped`. Trusted clients require additional scope to register. This can be configured with the `trusted_registration_scope` setting, which defaults to `realm`. + +#### Dynamic Client Registration + +With `client_registration` set to `dynamic`, any party can register a client with the authorization server. Optionally, a bearer token may be provided in the authorization header per RFC6750. If a valid access token is presented with a registration request, the client will be associated with the user represented by that token. + +```json +{ + // ... + "client_registration": "dynamic", + // ... +} +``` + +The following table indicates expected responses to *Dynamic Client Registration* requests. + +| trusted | w/token | w/scope | response | +|:-------:|:-------:|:-------:|----------:| +| | | | 201 | +| x | | | 403 | +| | x | | 201 | +| x | x | | 403 | +| x | x | x | 201 | +| | x | x | 201 | + + +#### Token-restricted Registration + +Client registration can be restricted so that a valid user access token is required by setting `client_registration` to `token`. In this case, any request without a token will fail. As with *Dynamic Client Registration*, in order to register a trusted client, the access token must have sufficient scope. + +```json +{ + // ... + "client_registration": "token", + // ... +} +``` + +| trusted | w/token | w/scope | response | +|:-------:|:-------:|:-------:|----------:| +| | | | 403 | +| x | | | 403 | +| | x | | 201 | +| x | x | | 403 | +| x | x | x | 201 | +| | x | x | 201 | + +#### Scoped Registration + +Third party registration can be restricted altogether with the `scoped` `client_registration` setting. In this case, all registration requires a prescribed `registration_scope`. + +```json +{ + // ... + "client_registration": "scoped", + // ... +} +``` + +| trusted | w/token | w/scope | response | +|:-------:|:-------:|:-------:|----------:| +| | | | 403 | +| x | | | 403 | +| | x | | 403 | +| x | x | | 403 | +| x | x | x | 201 | +| | x | x | 201 | + ## Client Properties #### redirect_uris diff --git a/server/getstarted.md b/getting-started.md similarity index 99% rename from server/getstarted.md rename to getting-started.md index 7028324..58c26ea 100644 --- a/server/getstarted.md +++ b/getting-started.md @@ -1,4 +1,4 @@ -## Get Started +## Getting Started ### Requirements diff --git a/permissions.md b/permissions.md index 7b85d44..b40ddcb 100644 --- a/permissions.md +++ b/permissions.md @@ -7,75 +7,3 @@ ## Users ## Clients - -## Dynamic Registration - -Anvil Connect can be configured for three types of client registration: `dynamic`, `token`, or `scoped`, each being more restrictive than the previous option. The default `client_registration` type is `scoped`. Trusted clients require additional scope to register. This can be configured with the `trusted_registration_scope` setting, which defaults to `realm`. - -### Dynamic Client Registration - -With `client_registration` set to `dynamic`, any party can register a client with the authorization server. Optionally, a bearer token may be provided in the authorization header per RFC6750. If a valid access token is presented with a registration request, the client will be associated with the user represented by that token. - -```json -{ - // ... - "client_registration": "dynamic", - // ... -} -``` - -The following table indicates expected responses to *Dynamic Client Registration* requests. - -| trusted | w/token | w/scope | response | -|:-------:|:-------:|:-------:|----------:| -| | | | 201 | -| x | | | 403 | -| | x | | 201 | -| x | x | | 403 | -| x | x | x | 201 | -| | x | x | 201 | - - -### Token-restricted Registration - -Client registration can be restricted so that a valid user access token is required by setting `client_registration` to `token`. In this case, any request without a token will fail. As with *Dynamic Client Registration*, in order to register a trusted client, the access token must have sufficient scope. - -```json -{ - // ... - "client_registration": "token", - // ... -} -``` - -| trusted | w/token | w/scope | response | -|:-------:|:-------:|:-------:|----------:| -| | | | 403 | -| x | | | 403 | -| | x | | 201 | -| x | x | | 403 | -| x | x | x | 201 | -| | x | x | 201 | - -### Scoped Registration - -Third party registration can be restricted altogether with the `scoped` `client_registration` setting. In this case, all registration requires a prescribed `registration_scope`. - -```json -{ - // ... - "client_registration": "scoped", - // ... -} -``` - -| trusted | w/token | w/scope | response | -|:-------:|:-------:|:-------:|----------:| -| | | | 403 | -| x | | | 403 | -| | x | | 403 | -| x | x | | 403 | -| x | x | x | 201 | -| | x | x | 201 | - - diff --git a/protocols.md b/protocols.md new file mode 100644 index 0000000..0c639f9 --- /dev/null +++ b/protocols.md @@ -0,0 +1,72 @@ +## Protocols + +Out of the box, Anvil Connect supports authenticating users with local +passwords, OAuth 1.0, OAuth 2.0, OpenID, LDAP, and Active Directory. We call +these authentication methods "protocols". + +For each supported protocol, we implement a module that supports any compliant +provider. This way, there's no need to write OAuth 2.0 code to support a new +OAuth 2.0-based service. Within Anvil Connect, [providers](providers/) and +protocols work together to separate the differences between authentication +methods from the parts that remain the same. + +In addition to what we ship with Anvil Connect, it only takes a small amount of +code in your project to authenticate using virtually any other method. You can +customize your Connect instance to use additional providers and protocols by +creating special directories in your project and adding some JavaScript. + +### Adding protocols + +To add a new protocol, create a `connect/protocols` directory in your Anvil +Connect project and add a JavaScript file named for the protocol. The filename +should be a camel cased string. + +This new module should export a Passport strategy that has two extra functions +appended to it: `verifier` and `initialize`. You can use any virtually existing +Passport strategy as a starting point, or write your own from scratch. + + +```javascript +/** + * Dependencies + */ + +var Strategy = require('passport-ANYTHING').Strategy; + + +/** + * Verifier + */ + +function verifier (req, [?..,] done) { + // ... +}; + +Strategy.verifier = verifier; + + +/** + * Initialize + */ + +function initialize (provider, configuration) { + return new Strategy([...], verifier); +} + +Strategy.initialize = initialize; + + +/** + * Export + */ + +module.exports = strategy; +``` + +The verifier function is the callback that get's invoked by Passport once +authentication has completed. + +#### Verifier + +#### Initialize + diff --git a/providers/LDAP.md b/providers/LDAP.md new file mode 100644 index 0000000..cbffcdf --- /dev/null +++ b/providers/LDAP.md @@ -0,0 +1,128 @@ +## LDAP + +Because of LDAP's flexible nature, LDAP support is provided in the form of a +provider template which can be used to handle custom LDAP attribute to OpenID +Connect claim scenarios. A basic provider that inherits this template without +modification is provided for convenience. + +LDAP providers can be configured as follows: + +```json +{ + // ... + "providers": { + "LDAP": { + "url": "ldap://corp.example.com", + "bindDn": "cn=admin,dc=example,dc=com", + "bindCredentials": "pass1234", + "searchBase": "ou=people,dc=example,dc=com", + "searchFilter": "(cn={{username}})" + } + } +} +``` + +A [full list of configuration options][passport-ldapauth-config] is available +from the passport-ldapauth library. + +By default, LDAP attributes map to OpenID Connect claims as such: + +OpenID Connect claim | LDAP attribute +-------------------- | -------------- +id | dn +email | mail +name | cn +given\_name | givenName +family\_name | sn +phone\_number | telephoneNumber +address.formatted | postalAddress +address.street\_address | street +address.locality | l +address.region | st +address.postal\_code | postalCode +address.country | co + +To customize these mappings, simply create your own provider in the `providers` +folder of your Anvil Connect instance. For example: + +```js +module.exports = function(config) { + return { + id: 'MyLDAP', + name: 'Example Corp.', + templates: [ 'LDAP' ], + mapping: { + id: 'uid', + name: 'displayName' + }; +}; +``` + + +### Active Directory + +The expected configuration format for the Active Directory provider is as +follows: + +```json +{ + ... + "providers": { + "ActiveDirectory": { + "url": "ldaps://corp.example.com", + "domainDn": "dc=example,dc=com", + "tlsOptions": { + "ca": "/path/to/the/self/signed/ca-cert.cer" + } + } + } +} +``` + +Anvil Connect also provides the `ActiveDirectory` provider template in the event +that you may be working with several domains at a time or if you would like to +customize certain aspects of the AD provider, such as the name. + +Here's an example provider that uses the template: + +```javascript +module.exports = function(config) { + return { + id: 'examplecorpad', + name: 'Example Corporation', + templates: [ 'ActiveDirectory' ] + }; +}; +``` + +To configure this provider, you would use `examplecorpad` in place of +`ActiveDirectory` in your configuration. + +```json +{ + ... + "providers": { + "examplecorpad": { ... } + } +} +``` + + +### Groups + +The LDAP provider will synchronize the user's role membership in Anvil Connect +with their group membership in the domain. In order to take advantage of this +feature, each LDAP group for which you wish to enable synchronization must have +a respective role in Connect named after the fully-qualified distinguished name +(FQDN) of the group in the directory. + +For example, if there exists a group in the directory service with FQDN +`CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the +user's role membership if there also exists a role in Connect named +`CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the +`nv add role` command: + +```bash +nv add role '{ "name": "CN=Group 1,OU=Groups,DC=example,DC=com" }' +``` + diff --git a/providers/OAuth.md b/providers/OAuth.md new file mode 100644 index 0000000..428d172 --- /dev/null +++ b/providers/OAuth.md @@ -0,0 +1,16 @@ +## OAuth 1.0 + +OAuth 1.0 providers require `oauth_consumer_key` and `oauth_consumer_secret`. + + +```json +{ + //... + "providers": { + "twitter": { + "oauth_consumer_key": "Consumer Key (API Key)", + "oauth_consumer_secret": "Consumer Secret" + } + } +} +``` diff --git a/providers/OAuth2.md b/providers/OAuth2.md new file mode 100644 index 0000000..4872234 --- /dev/null +++ b/providers/OAuth2.md @@ -0,0 +1,96 @@ +## OAuth 2.0 + +Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can +obtain these by registering your app with the respective provider. + +```json +{ + // ... + "providers": { + "facebook": { + "client_id": "App ID", + "client_secret": "App Secret" + } + } +} +``` + +OAuth 2.0 supports a `scope` authorization parameter, and some providers use it +to restricted access to specific resources. You can set scope for a provider +using the `scope` property with an array of strings. See provider API +documentation for specifics. + +```json +{ + //... + "providers": { + "google": { + "client_id": "Client ID", + "client_secret": "Client secret", + "scope": [ + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email" + ] + }, + "linkedin": { + "client_id": "Client ID", + "client_secret": "Client Secret", + "scope": [ + "r_basicprofile", + "r_fullprofile", + "r_emailaddress", + "r_network", + "r_contactinfo" + ] + } + } +} +``` + +### Creating a new OAuth 2.0 provider + +``` +/** + * GitHub + */ + +module.exports = function (config) { + return { + id: 'github', + name: 'GitHub', + protocol: 'OAuth2', + url: 'https://github.com', + redirect_uri: config.issuer + '/connect/github/callback', + endpoints: { + authorize: { + url: 'https://github.com/login/oauth/authorize', + method: 'POST', + }, + token: { + url: 'https://github.com/login/oauth/access_token', + method: 'POST', + auth: 'client_secret_post' + }, + user: { + url: 'https://api.github.com/user', + method: 'GET', + auth: { + header: 'Authorization', + scheme: 'Bearer' + } + } + }, + separator: ',', + mapping: { + id: 'id', + email: 'email', + name: 'name', + website: 'blog', + preferredUsername: 'login', + profile: 'html_url', + picture: 'avatar_url', + } + }; +}; +``` + diff --git a/providers/Password.md b/providers/Password.md new file mode 100644 index 0000000..cd51a02 --- /dev/null +++ b/providers/Password.md @@ -0,0 +1,17 @@ +## Password authentication + +To enable password authentication, add a `password` property to the `providers` +object with a value of `true`. When set to true, `password` _requires_ login +with username/password combination for the given providers every time they sign +in. If set to `false`, the user will be able to sign in without authenticating +with via username/password with the provider if as they are externally logged +into that provider already. + +```json +{ + // ... + "providers": { + "password": true + } +} +``` diff --git a/providers/README.md b/providers/README.md new file mode 100644 index 0000000..e12939d --- /dev/null +++ b/providers/README.md @@ -0,0 +1,88 @@ +## Providers + +A "provider" is a specific service providing authentication by means of a given +protocol. For example, Facebook, GitHub, and Dropbox are OAuth 2.0 providers. +They implement OAuth 2.0, and that's the protocol we use to interface with them +in the auth server. + +### Overview + +To add a new provider, create a `connect/providers` directory in your Anvil +Connect project and add a file named for the provider. The filename (not +including the .js extension) must be a valid JSON key since you'll be using it +in your configuration file. Let's say we want to add an OAuth 2.0 provider for +GitHub (although this provider is already supported). We'll create a file +called `connect/providers/github.js`. It should export a function that takes a +`config` argument which contains all settings for the server. + +``` +/** + * GitHub + */ + +module.exports = function (config) { + return { + id: 'github', + name: 'GitHub', + protocol: 'OAuth2', + // ... + // protocol specific properties + // ... + mapping: { + id: 'id', + email: 'email', + name: 'name', + website: 'blog', + preferredUsername: 'login', + profile: 'html_url', + picture: 'avatar_url', + } + }; +}; +``` + +When invoked, this function returns a simple JavaScript object containing all +the parameters needed by the corresponding protocol. + +#### id property + +The `id` property is used by the server to match a provider-specific +authorization request to this provider metadata. A good heuristic is to name +it the same as the filename (without the `.js` extension). + +#### protocol property + +The `protocol` property corresponds to the file name (sans extension) of the +protocol module you wish to use. Built in protocols you may wish to add a +provider for include `OAuth`, `OAuth2`, `OpenID`, `LDAP`, and +`ActiveDirectory`. If you add a [custom protocol](#?), use the basename of the +file for this value. + +#### mapping property + +The `mapping` property determines how user info from the provider gets mapped +into the OpenID Connect claims stored for each user inside Anvil Connect. On +the left are Anvil Connect user properties and on the right are property names +from the provider. You can reference nested properties using dot notation. +Given an object `{ info: { emails: { home: "foo@example.com" } } }`, your +mapping would contain `email: 'info.emails.home'`. The value side of a mapping +can also be a function, where the argument is the entire user info object from +the provider. + +#### Contributing commonly used providers + +Contributing new OAuth and OAuth 2.0 providers is one of the easiest ways to +get involved with the open source project. While many custom providers may not +be suitable for inclusion in the core of Anvil Connect, we greatly appreciate +pull requests for those that are. + +### Creating and configuring providers + +Instructions for adding different types of providers are given throughout +this folder. + +- [Password](Password.md) +- [OAuth 2.0](OAuth2.md) +- [OAuth](OAuth.md) +- [LDAP](LDAP.md) + diff --git a/server.md b/server.md deleted file mode 100644 index d5490ae..0000000 --- a/server.md +++ /dev/null @@ -1,610 +0,0 @@ -# Server - - -## Get Started - -### Requirements - -Anvil Connect is built with the latest versions of [Node.js](https://nodejs.org/) (0.12.x) and [Redis](http://redis.io/) (3.0.x). You'll need these installed on your system before you can run the server. In light of the Node shakeup that resulted in the Node Foundation's creation, it should be noted that Connect will be updating as Node continues to evolve. - - -### Install -To install Connect, run the npm install command: - -```bash -$ npm install -g anvil-connect -``` - -> **Note:** Windows support hasn't been tested, but you must have Python 2.7 and Visual Studio, which are required for compiling parts of Connect. If you would like to help contribute to Windows support, let us [know](https://github.com/anvilresearch/connect/issues), and we'll be able to work together. - -After npm is finished installing Connect, you will have access to the Connect command line tool to start working on integrating Connect into your project. - - -### Initialize - -#### Generate deployment - -Once you have installed the CLI, make a new directory and initialize your project. - -```bash -$ mkdir path/to/project && cd path/to/project -$ nv init -``` - - - -This will generate a file tree in the **current** directory: - -```bash -├── .bowerrc -├── .git -├── .gitignore -├── Dockerfile -├── bower.json -├── config -│   ├── development.json -│   ├── keys -│   │   ├── private.pem -│   │   └── public.pem -│   └── production.json -├── package.json -├── public -│   ├── images -│   │   └── anvil.svg -│   ├── javascript -│   │   └── session.js -│   └── stylesheets -│   └── app.css -├── server.js -└── views - ├── authorize.jade - ├── session.jade - ├── signin.jade - └── signup.jade -``` - -`nv init` will also write to the console the next steps needed to finish Connect setup once the file tree has been created. - -Anvil Connect aims to be easily customizable. Using a deployment repository allows you to serve your own static assets, customize views (HTML templates), manage dependencies and keep your configuration under version control. It also makes upgrading Anvil Connect as simple as changing the version number in `package.json`. - -#### Install Dependencies - -Now you can install npm and bower dependencies, if you want to run Connect locally. - -```bash -$ npm install -$ bower install -``` - -#### Initializing the database - -In current versions of Anvil Connect, database initialization is handled by the -server at run-time. See [Run](#Run) for details. - -`nv migrate` has been deprecated. - -### Run -#### Environments - -#### Commands -There are two environments to run the Connect server in, `development`, and `production`. The development server is for local testing, setup, and development on Connect itself. The production environment should be used when deployed to a live environment. - -To run the authorization server in `development` mode, you can run the server by simply starting it: - -```bash -# The following are equivalent, any of them will start the development server -$ nv serve -$ node server.js -$ npm start -``` - -To run the server in production, set `NODE_ENV` to `production`: - -```bash -# The following are equivalent, any of them will start the production server -$ nv serve --production -$ node server.js -e production -$ NODE_ENV=production node server.js -``` - -When Anvil Connect starts for the first time, it will check to see whether or -not the Redis server at the configured hostname and port has any data inside and -whether or not it contains data from a valid Anvil Connect instance. - -If Anvil Connect detects any existing data in the database, and it is not from -an Anvil Connect instance, it will halt with the following error: - -``` -Redis already contains data, but it doesn't seem to be an Anvil Connect database. -If you are SURE it is, start the server with --no-db-check to skip this check. -``` - -If you are sure that there is no conflicting data in Redis, for example, -in the event that you may have edited Redis's data manually, start Anvil Connect -with the `--no-db-check` flag. - -```bash -$ node server.js --no-db-check -``` - - -## Configure - -### JSON files - -Anvil Connect loads its configuration from a JSON file in the `config` directory of the current working directory for the process. File names must match the `NODE_ENV` value. If `NODE_ENV` is not set, `config/development.json` will be loaded. - -### Key pairs - -If you generated a deployment repository with `nv init`, a new RSA key pair will be generated for you in `config/keys`. This pair of files is required for signing and verifying tokens. We recommend using the generated files. We have set up key generation to lower the barrier to entry, as it is a tedious, precise process to do by hand. - -If you want or need to provide your own RSA key pair, you can obtain it using OpenSSL and import them to the proper location, `config/keys/private.pem` for the private key and `config/keys/public.pem` for the public key. - -``` -$ cd PROJECT_ROOT -$ mkdir -p config/keys -$ openssl genrsa -out config/keys/private.pem 2048 -$ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem -``` - -### Server Settings - -##### issuer - -**Type:** string - -**Use:** URI used to identify issuer of authentication - -**Description:** Fully qualified base URI of the authorization server; e.g., https://accounts.anvil.io - - -##### port - -**Type:** integer - -**Use:** port # the Connect server is run under - -**Description:** An integer value representing the port the server will be bound to, unless a PORT environment variable is provided. Defaults to 3000. - -##### cookie_secret - -**Type:** string - -**Use:** signing cookies - -**Description:** A string used for signing cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. - -##### session_secret - -**Type:** string - -**Use:** signing session cookies - -**Description:** A string used for signing session ID cookies. When you initialize a project, this value is generated for each of your environments. Treat it as confidential and always use separate values for each project and environment. - -##### client_registration - -**Type:** string - options: `dynamic`, `token`, or `scoped` - -**Use:** Assigning the type of client registration Connect uses - -**Description:** Anvil Connect can be configured for three types of client registration: `dynamic`, `token`, or `scoped`, each being more restrictive than the previous option. The default `client_registration` type is `scoped`. For more details, see the section titled [Client Registration](#client-registration-1). - -##### trusted_registration_scope - -**Type:** string - options: `realm`, Connect operator's own registered scope(s) - -**Use:** signing session cookies - -**Description:** `trusted_registration_scope` signals if a client is trusted or not - trusted clients require additional scope to register. It defaults to `realm`. - - -### Providers - -The providers setting is an object containing settings for various authentication methods. - -```json -{ - // ... - "providers": { ... } -} -``` - -You can see all the natively supported providers in the [providers directory](https://github.com/anvilresearch/connect/tree/master/providers) in the Anvil Connect repository on GitHub. If you want to use an provider not listed there, you can easily add support in your instance by creating a simple configuration file in a providers directory in your project repository. - -#### amr claim - -The `amr` claim is a part of the [OpenID Connect specification][oidcimplicit] -which stands for Authentication Methods References. It determines which methods -of authentication were used during the authentication request. - -For example, if a user signs in with their e-mail and password, then one of the -values of the `amr` claim will be `pwd` for password authentication. If the user -also used two-factor authentication with a disposable token, then the `amr` -claim will be `[ 'mfa', 'pwd', 'otp' ]` for multi-factor authentication, -password authentication, and one-time password. - -Anvil Connect supports taking advantage of the `amr` claim given that it is -defined for a particular provider. You can also configure your own value for the -amr claim for a particular provider in the configuration file. - -We use, and recommend the use of, the [IETF amr values draft][ietfamrvalues] -as a starting point for choosing amr values. - -For example, to define an `amr` value of `ad` for authenticating with Active -Directory: - -```json -{ - // ... - "providers": { - "ActiveDirectory": { - "amr": "ad", - // ... - } - } -} -``` - -#### Password authentication - -To enable password authentication, add a `password` property to the `providers` object with a value of `true`. When set to true, `password` _requires_ login with username/password combination for the given providers every time they sign in. If set to `false`, the user will be able to sign in without authenticating with via username/password with the provider if as they are externally logged into that provider already. - -```json -{ - // ... - "providers": { - "password": true - } -} -``` - -#### OAuth 2.0 - -Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can obtain these by registering your app with the respective provider. - -```json -{ - // ... - "providers": { - "facebook": { - "client_id": "App ID", - "client_secret": "App Secret" - } - } -} -``` - -OAuth 2.0 supports a `scope` authorization parameter, and some providers use it to restricted access to specific resources. You can set scope for a provider using the `scope` property with an array of strings. See provider API documentation for specifics. - -```json -{ - //... - "providers": { - "google": { - "client_id": "Client ID", - "client_secret": "Client secret", - "scope": [ - "https://www.googleapis.com/auth/userinfo.profile", - "https://www.googleapis.com/auth/userinfo.email" - ] - }, - "linkedin": { - "client_id": "Client ID", - "client_secret": "Client Secret", - "scope": [ - "r_basicprofile", - "r_fullprofile", - "r_emailaddress", - "r_network", - "r_contactinfo" - ] - } - } -} -``` - -#### OAuth 1.0 - -OAuth 1.0 providers require `oauth_consumer_key` and `oauth_consumer_secret`. - - -```json -{ - //... - "providers": { - "twitter": { - "oauth_consumer_key": "Consumer Key (API Key)", - "oauth_consumer_secret": "Consumer Secret" - } - } -} -``` -#### LDAP - -Because of LDAP's flexible nature, LDAP support is provided in the form of a -provider template which can be used to handle custom LDAP attribute to OpenID -Connect claim scenarios. A basic provider that inherits this template without -modification is provided for convenience. - -LDAP providers can be configured as follows: - -```json -{ - // ... - "providers": { - "LDAP": { - "url": "ldap://corp.example.com", - "bindDn": "cn=admin,dc=example,dc=com", - "bindCredentials": "pass1234", - "searchBase": "ou=people,dc=example,dc=com", - "searchFilter": "(cn={{username}})" - } - } -} -``` - -A [full list of configuration options][passport-ldapauth-config] is available -from the passport-ldapauth library. - -By default, LDAP attributes map to OpenID Connect claims as such: - -OpenID Connect claim | LDAP attribute --------------------- | -------------- -id | dn -email | mail -name | cn -given\_name | givenName -family\_name | sn -phone\_number | telephoneNumber -address.formatted | postalAddress -address.street\_address | street -address.locality | l -address.region | st -address.postal\_code | postalCode -address.country | co - -To customize these mappings, simply create your own provider in the `providers` -folder of your Anvil Connect instance. For example: - -```js -module.exports = function(config) { - return { - id: 'MyLDAP', - name: 'Example Corp.', - templates: [ 'LDAP' ], - mapping: { - id: 'uid', - name: 'displayName' - }; -}; -``` - - -##### Active Directory - -The expected configuration format for the Active Directory provider is as follows: - -```json -{ - ... - "providers": { - "ActiveDirectory": { - "url": "ldaps://corp.example.com", - "domainDn": "dc=example,dc=com", - "tlsOptions": { - "ca": "/path/to/the/self/signed/ca-cert.cer" - } - } - } -} -``` - -Anvil Connect also provides the `ActiveDirectory` provider template in the event that you may be working with several domains at a time or if you would like to customize certain aspects of the AD provider, such as the name. - -Here's an example provider that uses the template: - -```javascript -module.exports = function(config) { - return { - id: 'examplecorpad', - name: 'Example Corporation', - templates: [ 'ActiveDirectory' ] - }; -}; -``` - -To configure this provider, you would use `examplecorpad` in place of `ActiveDirectory` in your configuration. - -```json -{ - ... - "providers": { - "examplecorpad": { ... } - } -} -``` - - -##### Groups - -The LDAP provider will synchronize the user's role membership in Anvil Connect with their group membership in the domain. In order to take advantage of this feature, each LDAP group for which you wish to enable synchronization must have a respective role in Connect named after the fully-qualified distinguished name (FQDN) of the group in the directory. - -For example, if there exists a group in the directory service with FQDN `CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the user's role membership if there also exists a role in Connect named `CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the `nv add role` command: - -```bash -nv add role '{ "name": "CN=Group 1,OU=Groups,DC=example,DC=com" }' -``` - - -### Configuring the mailer - -Anvil Connect uses [nodemailer](https://github.com/andris9/Nodemailer) for sending emails for the purposes of email verification, and other functionality which is to come. - -The configuration file (e.g. development.json, production.json) must have a mailer object on the top level. The options for this configuration object are identical as that of [nodemailer transports](https://github.com/andris9/Nodemailer#use-the-default-smtp-transport), with the exception of an additionally required `from` property. The `from` property defines what e-mail address and name Anvil Connect will use in sending e-mails. It must be in the form `Name `. - -```json -{ - "mailer": { - "from": "Hello World ", - "view_engine": "hogan", - "service": "Gmail", - "auth": { - "user": "test@gmail.com", - "pass": "test" - } - }, -} -``` - -### Configuring e-mail verification - -Anvil Connect supports verifying user e-mail addresses to ensure that the user has ownership/control over their registered address. By default, configuring the mailer will enable email verification server-wide, but not require it. - -When a user signs in or signs up using e-mail/password based authentication, their e-mail address is unverified at first. If the user signs in or signs up using a third-party provider, then Connect will inherit the `email_verified` claim if available. Otherwise, the user's e-mail address stays unverified. - -#### Flow - -1. **Email verification enabled, but not required** - The user is able to sign up for an account with Anvil Connect, and sign in to clients as they normally would, without interruption. However, when the user signs up for the first time, they receive an email asking them to verify their email address. -2. **Email verification enabled and required** - When the user signs up for the first time with an unverified e-mail address, they are redirected to a page that prompts them to check their e-mail for a verification e-mail message. They are also given the option on that page to resend the e-mail in the event that it hasn't made its way through. Until the user verifies their e-mail, they are unable to authenticate with any client. - -#### Configuring verification for the entire server - -```json -{ - "emailVerification": { - "enable": true, - "require": false - }, - ... -} -``` - -#### Configuring verification for specific providers - -```json -{ - "providers": { - "password": { - "emailVerification": { - "enable": true, - "require": false - } - } - } - ... -} -``` - - -### Redis - -Anvil Connect requires access to a Redis database and uses the default host and port for a local instance. To use a remote Redis server, provide url and auth parameters under the "redis" object in your config. - -```json -{ - // ... - "redis": { - "url": "redis://HOST:PORT", - "auth": "PASSWORD" - } -} -``` - -You can also provide a `db` setting (integer) if you want to use a different Redis database. By default, Redis is configured to support 16 databases (0 - 15). This can be configured in the `redis.conf` file for your Redis installation. - -```json -{ - // ... - "redis": { - "db": 3 - } -} -``` - -### Logger - -Anvil Connect uses [bucker](https://github.com/nlf/bucker) for logging. Any valid configuration parameters for bucker can be included in the "logger" parameter in your config file. For example: - -```json -{ - // ... - "logger": { - "console": { - "color": false - }, - "syslog": { - "host": "localhost", - "port": 514, - "facility": 18 - } - } -} -``` - - -### OpenID Metadata - -[OpenID Provider Metadata](http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) default values can be overridden by defining them in the configuration file. Don't change these unless you know what you're doing. - - -## Customize - -### Views - -You can change the look and feel of Anvil Connect by editing the contents of the `views` directory in your project. There are four templates included in your views directory: `authorize`, `signin`, `signup`, and `session`. Connect works with any templating language supported by [consolidate.js](https://github.com/tj/consolidate.js). The `jade` templating language is used by default. You can configure your server to use a different templating language with the `view_engine` setting in your config files. - -#### Authorize - -The `authorize` view is the part of an OAuth 2.0 authorization flow that enables users to provide consent to an application to access some of their data. It is rendered when users authorize a third-party app. It is not displayed when authenticating `trusted` clients. - -#### Signin - -The `signin` view displays all configured user authentication options. - -#### Signup - -The `signup` view displays a signup form for local password authentication. - -#### Session - -This view is not intended to be visible to users. It gets loaded into a hidden iframe for clients that implement Single Sign-On using OpenID Connect Sessions. If you change it, be sure to leave the script references intact or this feature will not work correctly. - - - -#### Static Assets - -You can also add your own static assets to be served from the `public` directory at the root of your project. - -### E-mail templates - -E-mail templates are stored in the emails directory in the Connect root directory. The file extension matches the view engine to be used. The view engine can be configured by modifying the `view_engine` property on the `mailer` configuration object. Just as with views, any view engine supported by [consolidate.js](https://github.com/tj/consolidate.js) is supported by this property. By default, it is set to use [Hogan](https://github.com/twitter/hogan.js). - -#### E-mail verification - -The template for e-mail verification messages is `verifyEmail`. The template is provided with the provider name (`providerName`), verification URL (`verifyURL`), and user e-mail (`email`). - - - -## Deploy - - - -[oidcimplicit]: http://openid.net/specs/openid-connect-implicit-1_0.html -[ietfamrvalues]: http://tools.ietf.org/html/draft-jones-oauth-amr-values-00 -[passport-ldapauth-config]: https://github.com/vesse/node-ldapauth-fork/blob/master/lib/ldapauth.js#L22-L94 diff --git a/server/configure.md b/server/configuration.md similarity index 92% rename from server/configure.md rename to server/configuration.md index 52cdc86..e3b5d5b 100644 --- a/server/configure.md +++ b/server/configuration.md @@ -1,12 +1,27 @@ -## Configure +## Configuration -### JSON files +### Server Settings Anvil Connect loads its configuration from a JSON file in the `config` directory of the current working directory for the process. File names must match the `NODE_ENV` value. If `NODE_ENV` is not set, `config/development.json` will be loaded. +Setting | Type | Default | Description +------- | ---- | ------- | ----------- +**issuer** | string | (none) | URI used to identify issuer of authentication +**port** | integer | 3000 | Port the Connect server is bound to +**cookie_secret** | string | (generated) | Secret string used to sign secure cookies +**session_secret** | string | (generated) | Secret string used to sign session ID cookies +**client_registration** | string | `scoped` | Type of client registration - `dynamic`, `token`, or `scoped` ([Explanation](../clients.md#registration)) +**trusted_registration_scope** | string | `realm` | Scope used to identify trusted clients. + +### [Configuring Redis](redis.md) + +### [Configuring the mailer](mailer.md) + +### [Configuring the logger](logger.md) + ### Key pairs If you generated a deployment repository with `nv init`, a new RSA key pair @@ -25,14 +40,3 @@ $ mkdir -p config/keys $ openssl genrsa -out config/keys/private.pem 2048 $ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem ``` - -### Server Settings - -Setting | Type | Default | Description -------- | ---- | ------- | ----------- -**issuer** | string | (none) | URI used to identify issuer of authentication -**port** | integer | 3000 | Port the Connect server is bound to -**cookie_secret** | string | (generated) | Secret string used to sign secure cookies -**session_secret** | string | (generated) | Secret string used to sign session ID cookies -**client_registration** | string | `scoped` | Type of client registration - `dynamic`, `token`, or `scoped` ([Explanation](../clients.md#registration)) -**trusted_registration_scope** | string | `realm` | Scope used to identify trusted clients. diff --git a/server/protocols.md b/server/protocols.md deleted file mode 100644 index 4d54267..0000000 --- a/server/protocols.md +++ /dev/null @@ -1,211 +0,0 @@ -## User Authentication - -Out of the box, Anvil Connect supports authenticating users with local -passwords, OAuth 1.0, OAuth 2.0, OpenID, LDAP, and ActiveDirectory. We call -these authentication methods "protocols". - -A "provider" is a specific service providing authentication by means of a given -protocol. For example, Facebook, GitHub, and Dropbox are OAuth 2.0 providers. -They implement OAuth 2.0, and that's the protocol we use to interface with them -in the auth server. - -For each supported protocol, we implement a module that supports any compliant -provider. This way, there's no need to write OAuth 2.0 code to support a new -OAuth 2.0-based service. Within Anvil Connect, providers and protocols work -together to separate the differences between authentication methods from the -parts that remain the same. - -In addition to what we ship with Anvil Connect, it only takes a small amount of -code in your project to authenticate using virtually any other method. You can -customize your Connect instance to use additional providers and protocols by -creating special directories in your project and adding some JavaScript. - - - -### Adding Providers - -To add a new provider, create a `connect/providers` directory in your Anvil -Connect project and add a file named for the provider. The filename (not -including the .js extension) must be a valid JSON key since you'll be using it -in your configuration file. Let's say we want to add an OAuth 2.0 provider for -GitHub (although this provider is already supported). We'll create a file -called `connect/providers/github.js`. It should export a function that takes a -`config` argument which contains all settings for the server. - -``` -/** - * GitHub - */ - -module.exports = function (config) { - return { - id: 'github', - name: 'GitHub', - protocol: 'OAuth2', - // ... - // protocol specific properties - // ... - mapping: { - id: 'id', - email: 'email', - name: 'name', - website: 'blog', - preferredUsername: 'login', - profile: 'html_url', - picture: 'avatar_url', - } - }; -}; -``` - -When invoked, this function returns a simple JavaScript object containing all -the parameters needed by the corresponding protocol. - -#### id Property - -The `id` property is used by the server to match a provider-specific -authorization request to this provider metadata. A good heuristic is to name -it the same as the filename (without the `.js` extension). - -#### Protocol Property - -The `protocol` property corresponds to the file name (sans extension) of the -protocol module you wish to use. Built in protocols you may wish to add a -provider for include `OAuth`, `OAuth2`, `OpenID`, `LDAP`, and -`ActiveDirectory`. If you add a [custom protocol](#?), use the basename of the -file for this value. - -#### Mapping Property - -The `mapping` property determines how user info from the provider gets mapped -into the OpenID Connect claims stored for each user inside Anvil Connect. On -the left are Anvil Connect user properties and on the right are property names -from the provider. You can reference nested properties using dot notation. -Given an object `{ info: { emails: { home: "foo@example.com" } } }`, your -mapping would contain `email: 'info.emails.home'`. The value side of a mapping -can also be a function, where the argument is the entire user info object from -the provider. - - -#### OAuth 2.0 Providers - - -``` -/** - * GitHub - */ - -module.exports = function (config) { - return { - id: 'github', - name: 'GitHub', - protocol: 'OAuth2', - url: 'https://github.com', - redirect_uri: config.issuer + '/connect/github/callback', - endpoints: { - authorize: { - url: 'https://github.com/login/oauth/authorize', - method: 'POST', - }, - token: { - url: 'https://github.com/login/oauth/access_token', - method: 'POST', - auth: 'client_secret_post' - }, - user: { - url: 'https://api.github.com/user', - method: 'GET', - auth: { - header: 'Authorization', - scheme: 'Bearer' - } - } - }, - separator: ',', - mapping: { - id: 'id', - email: 'email', - name: 'name', - website: 'blog', - preferredUsername: 'login', - profile: 'html_url', - picture: 'avatar_url', - } - }; -}; -``` - - -#### OAuth 1.0 Providers - -#### LDAP Providers - -#### Active Directory Providers - -#### OpenID Providers - - -#### Contributing commonly used providers - -Contributing new OAuth and OAuth 2.0 providers is one of the easiest ways to -get involved with the open source project. While many custom providers may not -be suitable for inclusion in the core of Anvil Connect, we really appreciate -pull requests for those that are. - - - - -### Adding Protocols - -To add a new protocol, create a `connect/protocols` directory in your Anvil -Connect project and add a JavaScript file named for the protocol. The filename -should be a camel cased string. - -This new module should export a Passport strategy that has two extra functions -appended to it: `verifier` and `initialize`. You can use any virtually existing -Passport strategy as a starting point, or write your own from scratch. - - -```javascript -/** - * Dependencies - */ - -var Strategy = require('passport-ANYTHING').Strategy; - - -/** - * Verifier - */ - -function verifier (req, [?..,] done) { - // ... -}; - -Strategy.verifier = verifier; - - -/** - * Initialize - */ - -function initialize (provider, configuration) { - return new Strategy([...], verifier); -} - -Strategy.initialize = initialize; - - -/** - * Export - */ - -module.exports = strategy; -``` - -The verifier function is the callback that get's invoked by Passport once -authentication has completed. - -#### Verifier - -#### Initialize diff --git a/server/providers.md b/server/providers.md deleted file mode 100644 index 808e8d2..0000000 --- a/server/providers.md +++ /dev/null @@ -1,263 +0,0 @@ -### Providers - -The providers setting is an object containing settings for various -authentication methods. - -```json -{ - // ... - "providers": { ... } -} -``` - -You can see all the natively supported providers in the -[providers directory](https://github.com/anvilresearch/connect/tree/master/providers) -in the Anvil Connect repository on GitHub. If you want to use an provider not -listed there, you can easily add support in your instance by creating a simple -configuration file in a providers directory in your project repository. - -#### amr claim - -The `amr` claim is a part of the [OpenID Connect specification][oidcimplicit] -which stands for Authentication Methods References. It determines which methods -of authentication were used during the authentication request. - -For example, if a user signs in with their e-mail and password, then one of the -values of the `amr` claim will be `pwd` for password authentication. If the user -also used two-factor authentication with a disposable token, then the `amr` -claim will be `[ 'mfa', 'pwd', 'otp' ]` for multi-factor authentication, -password authentication, and one-time password. - -Anvil Connect supports taking advantage of the `amr` claim given that it is -defined for a particular provider. You can also configure your own value for the -amr claim for a particular provider in the configuration file. - -We use, and recommend the use of, the [IETF amr values draft][ietfamrvalues] -as a starting point for choosing amr values. - -For example, to define an `amr` value of `ad` for authenticating with Active -Directory: - -```json -{ - // ... - "providers": { - "ActiveDirectory": { - "amr": "ad", - // ... - } - } -} -``` - -#### Password authentication - -To enable password authentication, add a `password` property to the `providers` -object with a value of `true`. When set to true, `password` _requires_ login -with username/password combination for the given providers every time they sign -in. If set to `false`, the user will be able to sign in without authenticating -with via username/password with the provider if as they are externally logged -into that provider already. - -```json -{ - // ... - "providers": { - "password": true - } -} -``` - -#### OAuth 2.0 - -Most OAuth 2.0 providers only require a `client_id` and `client_secret`. You can -obtain these by registering your app with the respective provider. - -```json -{ - // ... - "providers": { - "facebook": { - "client_id": "App ID", - "client_secret": "App Secret" - } - } -} -``` - -OAuth 2.0 supports a `scope` authorization parameter, and some providers use it -to restricted access to specific resources. You can set scope for a provider -using the `scope` property with an array of strings. See provider API -documentation for specifics. - -```json -{ - //... - "providers": { - "google": { - "client_id": "Client ID", - "client_secret": "Client secret", - "scope": [ - "https://www.googleapis.com/auth/userinfo.profile", - "https://www.googleapis.com/auth/userinfo.email" - ] - }, - "linkedin": { - "client_id": "Client ID", - "client_secret": "Client Secret", - "scope": [ - "r_basicprofile", - "r_fullprofile", - "r_emailaddress", - "r_network", - "r_contactinfo" - ] - } - } -} -``` - -#### OAuth 1.0 - -OAuth 1.0 providers require `oauth_consumer_key` and `oauth_consumer_secret`. - - -```json -{ - //... - "providers": { - "twitter": { - "oauth_consumer_key": "Consumer Key (API Key)", - "oauth_consumer_secret": "Consumer Secret" - } - } -} -``` -#### LDAP - -Because of LDAP's flexible nature, LDAP support is provided in the form of a -provider template which can be used to handle custom LDAP attribute to OpenID -Connect claim scenarios. A basic provider that inherits this template without -modification is provided for convenience. - -LDAP providers can be configured as follows: - -```json -{ - // ... - "providers": { - "LDAP": { - "url": "ldap://corp.example.com", - "bindDn": "cn=admin,dc=example,dc=com", - "bindCredentials": "pass1234", - "searchBase": "ou=people,dc=example,dc=com", - "searchFilter": "(cn={{username}})" - } - } -} -``` - -A [full list of configuration options][passport-ldapauth-config] is available -from the passport-ldapauth library. - -By default, LDAP attributes map to OpenID Connect claims as such: - -OpenID Connect claim | LDAP attribute --------------------- | -------------- -id | dn -email | mail -name | cn -given\_name | givenName -family\_name | sn -phone\_number | telephoneNumber -address.formatted | postalAddress -address.street\_address | street -address.locality | l -address.region | st -address.postal\_code | postalCode -address.country | co - -To customize these mappings, simply create your own provider in the `providers` -folder of your Anvil Connect instance. For example: - -```js -module.exports = function(config) { - return { - id: 'MyLDAP', - name: 'Example Corp.', - templates: [ 'LDAP' ], - mapping: { - id: 'uid', - name: 'displayName' - }; -}; -``` - - -##### Active Directory - -The expected configuration format for the Active Directory provider is as -follows: - -```json -{ - ... - "providers": { - "ActiveDirectory": { - "url": "ldaps://corp.example.com", - "domainDn": "dc=example,dc=com", - "tlsOptions": { - "ca": "/path/to/the/self/signed/ca-cert.cer" - } - } - } -} -``` - -Anvil Connect also provides the `ActiveDirectory` provider template in the event -that you may be working with several domains at a time or if you would like to -customize certain aspects of the AD provider, such as the name. - -Here's an example provider that uses the template: - -```javascript -module.exports = function(config) { - return { - id: 'examplecorpad', - name: 'Example Corporation', - templates: [ 'ActiveDirectory' ] - }; -}; -``` - -To configure this provider, you would use `examplecorpad` in place of -`ActiveDirectory` in your configuration. - -```json -{ - ... - "providers": { - "examplecorpad": { ... } - } -} -``` - - -##### Groups - -The LDAP provider will synchronize the user's role membership in Anvil Connect -with their group membership in the domain. In order to take advantage of this -feature, each LDAP group for which you wish to enable synchronization must have -a respective role in Connect named after the fully-qualified distinguished name -(FQDN) of the group in the directory. - -For example, if there exists a group in the directory service with FQDN -`CN=Group 1,OU=Groups,DC=example,DC=com`, that group will only influence the -user's role membership if there also exists a role in Connect named -`CN=Group 1,OU=Groups,DC=example,DC=com`. You can create this role using the -`nv add role` command: - -```bash -nv add role '{ "name": "CN=Group 1,OU=Groups,DC=example,DC=com" }' -``` - From 88ba3f61e9c94f85df74ce79aee6a5df2950e61f Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Mon, 24 Aug 2015 17:47:45 -0700 Subject: [PATCH 09/20] Add link to configuration to getting started --- getting-started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/getting-started.md b/getting-started.md index 58c26ea..9f6349f 100644 --- a/getting-started.md +++ b/getting-started.md @@ -246,3 +246,4 @@ connect: image: /connect ``` +### [Configuring the server](server/configuration.md) From 6c38d84d82e80d12cffccdfcf2010176b3439806 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 09:47:30 -0700 Subject: [PATCH 10/20] fix typos and minor adjustments for readability --- getting-started.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/getting-started.md b/getting-started.md index 9f6349f..7462ccd 100644 --- a/getting-started.md +++ b/getting-started.md @@ -4,7 +4,7 @@ Anvil Connect works with the latest versions of [Node.js][nodejs] (0.12.x) or [io.js][iojs] (3.x.x) and [Redis][redis] (3.0.x) and is tested on -[Debian][debian], [Unbuntu][ubuntu], [Alpine][alpine] Linux distributions, and +[Debian][debian], [Ubuntu][ubuntu], [Alpine][alpine] Linux distributions, and Mac OS X. The server and its dependencies can optionally run inside [Docker][docker] @@ -47,7 +47,7 @@ $ nvl init This command will prompt you for some essential information and choices about your deployment. -With default options, this command will generate all the files you +With default options, `nv init` will generate all the files you need to customize and run Anvil Connect, with or without Docker, Redis and nginx, depending on your prompt selections. @@ -162,7 +162,8 @@ First, you'll want to ensure a few things are in order. If you're running on Linux, Anvil Connect will be bound to localhost and/or the IP of your computer/server. Once the containers are running, you should be able -to reach the service at `https://0.0.0.0`. +to reach the service at `https://0.0.0.0`, `https://127.0.0.1`, or +`https://localhost`. On Mac once you've installed the [Docker Toolbox][docker-toolbox] you can get @@ -176,8 +177,8 @@ $ docker-machine ip default To work with your Anvil Connect instance locally, it's a good idea to make an entry in your `/etc/hosts` file. For example, on a Mac, you'll want to -associate the (sub)domain you provided the generator with `boot2docker` IP -address. +associate the (sub)domain you provided the generator with the IP address of +your Docker host. ```bash 192.168.99.100 connect.example.io From c987d1f39749d9229f7dcb81befa8adf75253bc0 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 09:59:11 -0700 Subject: [PATCH 11/20] update key pair information and examples --- server/configuration.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/server/configuration.md b/server/configuration.md index e3b5d5b..a164aa4 100644 --- a/server/configuration.md +++ b/server/configuration.md @@ -25,18 +25,18 @@ Setting | Type | Default | Description ### Key pairs If you generated a deployment repository with `nv init`, a new RSA key pair -will be generated for you in `config/keys`. This pair of files is required for -signing and verifying tokens. We recommend using the generated files. We have -set up key generation to lower the barrier to entry, as it is a tedious, -precise process to do by hand. +will be generated for you in `connect/config/keys`. This pair of files is +required for signing and verifying tokens. We recommend using the generated +files. If the server does not find key pairs when starting, it will attempt to +generate them for you using the OpenSSL package installed on your system. If you want or need to provide your own RSA key pair, you can obtain it using -OpenSSL and import them to the proper location, `config/keys/private.pem` for -the private key and `config/keys/public.pem` for the public key. +OpenSSL and import them to the proper location, `connect/config/keys/private.pem` +for the private key and `connect/config/keys/public.pem` for the public key. ``` $ cd PROJECT_ROOT -$ mkdir -p config/keys -$ openssl genrsa -out config/keys/private.pem 2048 -$ openssl rsa -pubout -in config/keys/private.pem -out config/keys/public.pem +$ mkdir -p connect/config/keys +$ openssl genrsa -out connect/config/keys/private.pem 4096 +$ openssl rsa -pubout -in connect/config/keys/private.pem -out connect/config/keys/public.pem ``` From 6875167b4771e6d9122017df4b3fc1ae57869f97 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 10:01:11 -0700 Subject: [PATCH 12/20] readability --- server/configuration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/configuration.md b/server/configuration.md index a164aa4..53b0c89 100644 --- a/server/configuration.md +++ b/server/configuration.md @@ -26,9 +26,9 @@ Setting | Type | Default | Description If you generated a deployment repository with `nv init`, a new RSA key pair will be generated for you in `connect/config/keys`. This pair of files is -required for signing and verifying tokens. We recommend using the generated -files. If the server does not find key pairs when starting, it will attempt to -generate them for you using the OpenSSL package installed on your system. +required for signing and verifying tokens. If the server does not find key +pairs when starting, it will attempt to generate them for you using the OpenSSL +package installed on your system. If you want or need to provide your own RSA key pair, you can obtain it using OpenSSL and import them to the proper location, `connect/config/keys/private.pem` From 4a632d7250a7c4c1818a9903eb3c7b970691c750 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 10:05:12 -0700 Subject: [PATCH 13/20] link for installing OpenSSL on Windows --- server/configuration.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/configuration.md b/server/configuration.md index 53b0c89..3c9a2fc 100644 --- a/server/configuration.md +++ b/server/configuration.md @@ -28,7 +28,10 @@ If you generated a deployment repository with `nv init`, a new RSA key pair will be generated for you in `connect/config/keys`. This pair of files is required for signing and verifying tokens. If the server does not find key pairs when starting, it will attempt to generate them for you using the OpenSSL -package installed on your system. +package installed on your system. Mac and most Unix and Linux based systems +include OpenSSL by default. You can also [install it on Windows][ssl-windows]. + +[ssl-windows]: https://slproweb.com/products/Win32OpenSSL.html If you want or need to provide your own RSA key pair, you can obtain it using OpenSSL and import them to the proper location, `connect/config/keys/private.pem` From 753891960ab3c8274280b518a50cc587b8f1c3b3 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 10:08:36 -0700 Subject: [PATCH 14/20] manual key pair generation --- server/configuration.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/configuration.md b/server/configuration.md index 3c9a2fc..1cd3b66 100644 --- a/server/configuration.md +++ b/server/configuration.md @@ -33,9 +33,8 @@ include OpenSSL by default. You can also [install it on Windows][ssl-windows]. [ssl-windows]: https://slproweb.com/products/Win32OpenSSL.html -If you want or need to provide your own RSA key pair, you can obtain it using -OpenSSL and import them to the proper location, `connect/config/keys/private.pem` -for the private key and `connect/config/keys/public.pem` for the public key. +If you want to provide your own RSA key pair files, you can generate them +manually with OpenSSL. ``` $ cd PROJECT_ROOT From 15411cefaebea34e15c64dcfecac2fd6239e89d5 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 10:58:24 -0700 Subject: [PATCH 15/20] updated providers explanations --- providers/OAuth2.md | 7 +++++++ providers/Password.md | 16 +++++++++------- providers/README.md | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/providers/OAuth2.md b/providers/OAuth2.md index 4872234..4d8dcee 100644 --- a/providers/OAuth2.md +++ b/providers/OAuth2.md @@ -49,6 +49,13 @@ documentation for specifics. ### Creating a new OAuth 2.0 provider +To integrate with a provider we don't support out of the box, you can create +your own provider definition in a custom `connect/providers` directory in your +project. You can use [officially supported provider definitions][supported-providers] +as examples. + +[supported-providers]: https://github.com/anvilresearch/connect/tree/master/providers + ``` /** * GitHub diff --git a/providers/Password.md b/providers/Password.md index cd51a02..00e9b2f 100644 --- a/providers/Password.md +++ b/providers/Password.md @@ -1,17 +1,19 @@ ## Password authentication -To enable password authentication, add a `password` property to the `providers` -object with a value of `true`. When set to true, `password` _requires_ login -with username/password combination for the given providers every time they sign -in. If set to `false`, the user will be able to sign in without authenticating -with via username/password with the provider if as they are externally logged -into that provider already. +Local password authentication can be configured easily by adding a password +object to the providers section of your configuration files. + +Anvil Connect uses the mellt package to test password strength. You can +configure the minimum number of days required to crack a password with the +`daysToCrack` setting, which defaults to 14. ```json { // ... "providers": { - "password": true + "password": { + "daysToCrack": 21 + } } } ``` diff --git a/providers/README.md b/providers/README.md index e12939d..a33625b 100644 --- a/providers/README.md +++ b/providers/README.md @@ -69,6 +69,40 @@ mapping would contain `email: 'info.emails.home'`. The value side of a mapping can also be a function, where the argument is the entire user info object from the provider. +#### amr claim + +The `amr` claim is a part of the [OpenID Connect specification][oidcimplicit] +which stands for Authentication Methods References. It determines which methods +of authentication were used during the authentication request. + +For example, if a user signs in with their e-mail and password, then one of the +values of the `amr` claim will be `pwd` for password authentication. If the user +also used two-factor authentication with a disposable token, then the `amr` +claim will be `[ 'mfa', 'pwd', 'otp' ]` for multi-factor authentication, +password authentication, and one-time password. + +Anvil Connect supports taking advantage of the `amr` claim given that it is +defined for a particular provider. You can also configure your own value for the +amr claim for a particular provider in the configuration file. + +We use, and recommend the use of, the [IETF amr values draft][ietfamrvalues] +as a starting point for choosing amr values. + +For example, to define an `amr` value of `ad` for authenticating with Active +Directory: + +```json +{ + // ... + "providers": { + "ActiveDirectory": { + "amr": "ad", + // ... + } + } +} +``` + #### Contributing commonly used providers Contributing new OAuth and OAuth 2.0 providers is one of the easiest ways to @@ -84,5 +118,5 @@ this folder. - [Password](Password.md) - [OAuth 2.0](OAuth2.md) - [OAuth](OAuth.md) -- [LDAP](LDAP.md) +- [LDAP and Active Directory](LDAP.md) From 3ec276dc6d445b97898d51d417920b44b9353f03 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 11:04:33 -0700 Subject: [PATCH 16/20] split email verification info to separate file --- server/email-verification.md | 53 +++++++++++++++++++++++++++++++++++ server/mailer.md | 54 ------------------------------------ 2 files changed, 53 insertions(+), 54 deletions(-) create mode 100644 server/email-verification.md diff --git a/server/email-verification.md b/server/email-verification.md new file mode 100644 index 0000000..969b400 --- /dev/null +++ b/server/email-verification.md @@ -0,0 +1,53 @@ +### Configuring e-mail verification + +Anvil Connect supports verifying user e-mail addresses to ensure that the user +has ownership/control over their registered address. By default, configuring the +mailer will enable email verification server-wide, but not require it. + +When a user signs in or signs up using e-mail/password based authentication, +their e-mail address is unverified at first. If the user signs in or signs up +using a third-party provider, then Connect will inherit the `email_verified` +claim if available. Otherwise, the user's e-mail address stays unverified. + +#### Flow + +1. **Email verification enabled, but not required** + The user is able to sign up for an account with Anvil Connect, and sign in + to clients as they normally would, without interruption. However, when the + user signs up for the first time, they receive an email asking them to verify + their email address. +2. **Email verification enabled and required** + When the user signs up for the first time with an unverified e-mail address, + they are redirected to a page that prompts them to check their e-mail for a + verification e-mail message. They are also given the option on that page to + resend the e-mail in the event that it hasn't made its way through. Until the + user verifies their e-mail, they are unable to authenticate with any client. + +#### Configuring verification for the entire server + +```json +{ + "emailVerification": { + "enable": true, + "require": false + }, + ... +} +``` + +#### Configuring verification for specific providers + +```json +{ + "providers": { + "password": { + "emailVerification": { + "enable": true, + "require": false + } + } + } + ... +} +``` + diff --git a/server/mailer.md b/server/mailer.md index cac60ad..88da318 100644 --- a/server/mailer.md +++ b/server/mailer.md @@ -24,57 +24,3 @@ e-mails. It must be in the form `Name `. }, } ``` - -### Configuring e-mail verification - -Anvil Connect supports verifying user e-mail addresses to ensure that the user -has ownership/control over their registered address. By default, configuring the -mailer will enable email verification server-wide, but not require it. - -When a user signs in or signs up using e-mail/password based authentication, -their e-mail address is unverified at first. If the user signs in or signs up -using a third-party provider, then Connect will inherit the `email_verified` -claim if available. Otherwise, the user's e-mail address stays unverified. - -#### Flow - -1. **Email verification enabled, but not required** - The user is able to sign up for an account with Anvil Connect, and sign in - to clients as they normally would, without interruption. However, when the - user signs up for the first time, they receive an email asking them to verify - their email address. -2. **Email verification enabled and required** - When the user signs up for the first time with an unverified e-mail address, - they are redirected to a page that prompts them to check their e-mail for a - verification e-mail message. They are also given the option on that page to - resend the e-mail in the event that it hasn't made its way through. Until the - user verifies their e-mail, they are unable to authenticate with any client. - -#### Configuring verification for the entire server - -```json -{ - "emailVerification": { - "enable": true, - "require": false - }, - ... -} -``` - -#### Configuring verification for specific providers - -```json -{ - "providers": { - "password": { - "emailVerification": { - "enable": true, - "require": false - } - } - } - ... -} -``` - From f0ff26b735020252793b2ce237569a95d64416f8 Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 11:08:08 -0700 Subject: [PATCH 17/20] update Redis config info --- server/redis.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/redis.md b/server/redis.md index 97ff321..f3fdc9b 100644 --- a/server/redis.md +++ b/server/redis.md @@ -1,22 +1,26 @@ ### Redis -Anvil Connect requires access to a Redis database and uses the default host and -port for a local instance. To use a remote Redis server, provide url and auth -parameters under the "redis" object in your config. +Anvil Connect requires access to a Redis database and uses the default host and +port for a local instance. To use a remote Redis server, provide host, port, +and password parameters under the "redis" object in your config. ```json { // ... "redis": { - "url": "redis://HOST:PORT", - "auth": "PASSWORD" + "host": "HOST", + "port": "PORT", + "password": "PASSWORD" } } ``` -You can also provide a `db` setting (integer) if you want to use a different -Redis database. By default, Redis is configured to support 16 databases -(0 - 15). This can be configured in the `redis.conf` file for your Redis +Configuration options for Redis are identical to that of the +[supported options for ioredis][ioredis-options]. + +You can also provide a `db` setting (integer) if you want to use a different +Redis database. By default, Redis is configured to support 16 databases +(0 - 15). This can be configured in the `redis.conf` file for your Redis installation. ```json @@ -27,4 +31,3 @@ installation. } } ``` - From 196c70d2d254d47999011e7c9689731a5b3c0dad Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 11:10:33 -0700 Subject: [PATCH 18/20] add OIDC metadata info --- server/configuration.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/configuration.md b/server/configuration.md index 1cd3b66..d655285 100644 --- a/server/configuration.md +++ b/server/configuration.md @@ -16,6 +16,15 @@ Setting | Type | Default | Description **client_registration** | string | `scoped` | Type of client registration - `dynamic`, `token`, or `scoped` ([Explanation](../clients.md#registration)) **trusted_registration_scope** | string | `realm` | Scope used to identify trusted clients. + +### OpenID Metadata + +[OpenID Provider Metadata](http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) +default values can be overridden by defining them in the configuration file. +Don't change these unless you know what you're doing. + + + ### [Configuring Redis](redis.md) ### [Configuring the mailer](mailer.md) From 01e512276593f694b6e38af7620a69596414b18b Mon Sep 17 00:00:00 2001 From: Christian Smith Date: Tue, 25 Aug 2015 11:23:11 -0700 Subject: [PATCH 19/20] customizing views, emails, and static assets --- server/customization.md | 13 +++++++++++++ server/email-verification.md | 2 +- server/logger.md | 2 +- server/mailer.md | 2 +- server/redis.md | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 server/customization.md diff --git a/server/customization.md b/server/customization.md new file mode 100644 index 0000000..d2081d9 --- /dev/null +++ b/server/customization.md @@ -0,0 +1,13 @@ +## Customization + +By default, Anvil Connect uses html templates, email templates and static +assets from inside the `anvil-connect` npm package. You can completely customize +the look and feel of Anvil Connect by overriding these files in the `views`, +`email`, and `public` directories in your project. + +To do this, simply copy the file you want to work with from +`node_modules/anvil-connect/[views|email|public]` into a corresponding directory +in your project and modify it however you want. When Anvil Connect runs, it will +use your custom files. + + diff --git a/server/email-verification.md b/server/email-verification.md index 969b400..c6c6085 100644 --- a/server/email-verification.md +++ b/server/email-verification.md @@ -1,4 +1,4 @@ -### Configuring e-mail verification +## Configuring e-mail verification Anvil Connect supports verifying user e-mail addresses to ensure that the user has ownership/control over their registered address. By default, configuring the diff --git a/server/logger.md b/server/logger.md index 05f05c0..568b2c8 100644 --- a/server/logger.md +++ b/server/logger.md @@ -1,4 +1,4 @@ -### Logger +## Logger Anvil Connect uses [bucker](https://github.com/nlf/bucker) for logging. Any valid configuration parameters for bucker can be included in the "logger" diff --git a/server/mailer.md b/server/mailer.md index 88da318..8547701 100644 --- a/server/mailer.md +++ b/server/mailer.md @@ -1,4 +1,4 @@ -### Configuring the mailer +## Configuring the mailer Anvil Connect uses [nodemailer](https://github.com/andris9/Nodemailer) for sending emails for the purposes of email verification, and other functionality diff --git a/server/redis.md b/server/redis.md index f3fdc9b..53b71af 100644 --- a/server/redis.md +++ b/server/redis.md @@ -1,4 +1,4 @@ -### Redis +## Redis Anvil Connect requires access to a Redis database and uses the default host and port for a local instance. To use a remote Redis server, provide host, port, From 3516a5fcc0c1588946293409f4ccade51683351a Mon Sep 17 00:00:00 2001 From: Vartan Simonian Date: Tue, 25 Aug 2015 11:24:38 -0700 Subject: [PATCH 20/20] Update email-verification.md Adjust header leveling --- server/email-verification.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/email-verification.md b/server/email-verification.md index c6c6085..8084250 100644 --- a/server/email-verification.md +++ b/server/email-verification.md @@ -9,7 +9,7 @@ their e-mail address is unverified at first. If the user signs in or signs up using a third-party provider, then Connect will inherit the `email_verified` claim if available. Otherwise, the user's e-mail address stays unverified. -#### Flow +### Flow 1. **Email verification enabled, but not required** The user is able to sign up for an account with Anvil Connect, and sign in @@ -23,7 +23,7 @@ claim if available. Otherwise, the user's e-mail address stays unverified. resend the e-mail in the event that it hasn't made its way through. Until the user verifies their e-mail, they are unable to authenticate with any client. -#### Configuring verification for the entire server +### Configuring verification for the entire server ```json { @@ -35,7 +35,7 @@ claim if available. Otherwise, the user's e-mail address stays unverified. } ``` -#### Configuring verification for specific providers +### Configuring verification for specific providers ```json {