Skip to content

Commit

Permalink
Clean readme & move doc (#1129)
Browse files Browse the repository at this point in the history
* Change Readme organization

* Add gitbook table of contents

* Readme and doc improvements

* Change links to https protocol
  • Loading branch information
Maicol Bentancor authored and zachfeldman committed Apr 3, 2018
1 parent 5857e39 commit 23ed467
Show file tree
Hide file tree
Showing 20 changed files with 1,090 additions and 921 deletions.
956 changes: 35 additions & 921 deletions README.md

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions SUMMARY.md
@@ -0,0 +1,27 @@
# Summary

* Introduction
* [Installation](README.md#installation)
* [Need help?](README.md#need-help)
* [Live demos](README.md#live-demos)
* Configuration
* [Introduction](docs/config/README.md)
* [Initializer Settings](docs/config/initialization.md)
* [OmniAuth](docs/config/omniauth.md)
* [Email Authentication](docs/config/email_auth.md)
* [Customizing Devise Verbiage](docs/config/devise.md)
* [Cross Origin Requests (CORS)](docs/config/cors.md)
* Usage
* [Introduction](docs/usage/README.md)
* [Mounting Routes](docs/usage/routes.md)
* [Controller Integration](docs/usage/controller_methods.md)
* [Model Integration](docs/usage/model_concerns.md)
* [Using Multiple User Classes](docs/usage/multiple_models.md)
* [Excluding Modules](docs/usage/excluding_models.md)
* [Custom Controller/Email Overrides](docs/usage/overrides.md)
* [Testing](docs/usage/testing.md)
* [FAQ](docs/faq.md)
* [Conceptual Diagrams](docs/conceptual.md)
* [Token Management](docs/conceptual.md#about-token-management)
* [Batch Requests](docs/conceptual.md#about-batch-requests)
* [Security](docs/security.md)
50 changes: 50 additions & 0 deletions docs/conceptual.md
@@ -0,0 +1,50 @@
# Conceptual

None of the following information is required to use this gem, but read on if you're curious.

## About token management

Tokens should be invalidated after each request to the API. The following diagram illustrates this concept:

![password reset flow](https://github.com/lynndylanhurley/ng-token-auth/raw/master/test/app/images/flow/token-update-detail.jpg)

During each request, a new token is generated. The `access-token` header that should be used in the next request is returned in the `access-token` header of the response to the previous request. The last request in the diagram fails because it tries to use a token that was invalidated by the previous request.

The only case where an expired token is allowed is during [batch requests](#about-batch-requests).

These measures are taken by default when using this gem.

## About batch requests

By default, the API should update the auth token for each request ([read more](#about-token-management)). But sometimes it's necessary to make several concurrent requests to the API, for example:

##### Batch request example

~~~javascript
$scope.getResourceData = function() {

$http.get('/api/restricted_resource_1').success(function(resp) {
// handle response
$scope.resource1 = resp.data;
});

$http.get('/api/restricted_resource_2').success(function(resp) {
// handle response
$scope.resource2 = resp.data;
});
};
~~~

In this case, it's impossible to update the `access-token` header for the second request with the `access-token` header of the first response because the second request will begin before the first one is complete. The server must allow these batches of concurrent requests to share the same auth token. This diagram illustrates how batch requests are identified by the server:

![batch request overview](https://github.com/lynndylanhurley/ng-token-auth/raw/master/test/app/images/flow/batch-request-overview.jpg)

The "5 second" buffer in the diagram is the default used this gem.

The following diagram details the relationship between the client, server, and access tokens used over time when dealing with batch requests:

![batch request detail](https://github.com/lynndylanhurley/ng-token-auth/raw/master/test/app/images/flow/batch-request-detail.jpg)

Note that when the server identifies that a request is part of a batch request, the user's auth token is not updated. The auth token will be updated and returned with the first request in the batch, and the subsequent requests in the batch will not return a token. This is necessary because the order of the responses cannot be guaranteed to the client, and we need to be sure that the client does not receive an outdated token *after* the the last valid token is returned.

This gem automatically manages batch requests. You can change the time buffer for what is considered a batch request using the `batch_request_buffer_throttle` parameter in `config/initializers/devise_token_auth.rb`.
43 changes: 43 additions & 0 deletions docs/config/README.md
@@ -0,0 +1,43 @@
## Configuration TL;DR

You will need to create a [user model](/docs/usage/model_concerns.md), [define routes](/docs/usage/routes.md), [include concerns](/docs/usage/controller_methods.md), and you may want to alter some of the [default settings](initialization.md) for this gem. Run the following command for an easy one-step installation:

~~~bash
rails g devise_token_auth:install [USER_CLASS] [MOUNT_PATH]
~~~

**Example**:

~~~bash
rails g devise_token_auth:install User auth
~~~

This generator accepts the following optional arguments:

| Argument | Default | Description |
|---|---|---|
| USER_CLASS | `User` | The name of the class to use for user authentication. |
| MOUNT_PATH | `auth` | The path at which to mount the authentication routes. [Read more](#usage-tldr). |

The following events will take place when using the install generator:

* An initializer will be created at `config/initializers/devise_token_auth.rb`. [Read more](initialization.md).

* A model will be created in the `app/models` directory. If the model already exists, a concern will be included at the top of the file. [Read more](/docs/usage/model_concerns.md).

* Routes will be appended to file at `config/routes.rb`. [Read more](/docs/usage/routes.md).

* A concern will be included by your application controller at `app/controllers/application_controller.rb`. [Read more](/docs/usage/controller_methods.md).

* A migration file will be created in the `db/migrate` directory. Inspect the migrations file, add additional columns if necessary, and then run the migration:

~~~bash
rake db:migrate
~~~

You may also need to configure the following items:

* **OmniAuth providers** when using 3rd party oauth2 authentication. [Read more](omniauth.md).
* **Cross Origin Request Settings** when using cross-domain clients. [Read more](cors.md).
* **Email** when using email registration. [Read more](email-auth.md).
* **Multiple model support** may require additional steps. [Read more](/docs/usage/multiple_models.md).
30 changes: 30 additions & 0 deletions docs/config/cors.md
@@ -0,0 +1,30 @@
## CORS

If your API and client live on different domains, you will need to configure your Rails API to allow [cross origin requests](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). The [rack-cors](https://github.com/cyu/rack-cors) gem can be used to accomplish this.

The following **dangerous** example will allow cross domain requests from **any** domain. Make sure to whitelist only the needed domains.

##### Example rack-cors configuration:
~~~ruby
# gemfile
gem 'rack-cors', :require => 'rack/cors'

# config/application.rb
module YourApp
class Application < Rails::Application
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
expose: ['access-token', 'expiry', 'token-type', 'uid', 'client'],
methods: [:get, :post, :options, :delete, :put]
end
end
end
end
~~~

Make extra sure that the `Access-Control-Expose-Headers` includes `access-token`, `expiry`, `token-type`, `uid`, and `client` (as is set in the example above by the`:expose` param). If your client experiences erroneous 401 responses, this is likely the cause.

CORS may not be possible with older browsers (IE8, IE9). I usually set up a proxy for those browsers. See the [ng-token-auth readme](https://github.com/lynndylanhurley/ng-token-auth) or the [jToker readme](https://github.com/lynndylanhurley/j-toker) for more information.
13 changes: 13 additions & 0 deletions docs/config/devise.md
@@ -0,0 +1,13 @@
## Customizing Devise Verbiage

Devise Token Auth ships with intelligent default wording for everything you need. But that doesn't mean you can't make it more awesome. You can override the [devise defaults](https://github.com/plataformatec/devise/blob/master/config/locales/en.yml) by creating a YAML file at `config/locales/devise.en.yml` and assigning whatever custom values you want. For example, to customize the subject line of your devise e-mails, you could do this:

~~~yaml
en:
devise:
mailer:
confirmation_instructions:
subject: "Please confirm your e-mail address"
reset_password_instructions:
subject: "Reset password request"
~~~
16 changes: 16 additions & 0 deletions docs/config/email_auth.md
@@ -0,0 +1,16 @@
## Email authentication
If you wish to use email authentication, you must configure your Rails application to send email. [Read here](http://guides.rubyonrails.org/action_mailer_basics.html) for more information.

I recommend using [mailcatcher](https://mailcatcher.me/) for development.

##### mailcatcher development example configuration:
~~~ruby
# config/environments/development.rb
Rails.application.configure do
config.action_mailer.default_url_options = { host: 'your-dev-host.dev' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: 'your-dev-host.dev', port: 1025 }
end
~~~

If you wish to send custom e-mails instead of using the default devise templates, you can [do that too](/docs/usage/overrides.md#email-template-overrides).
33 changes: 33 additions & 0 deletions docs/config/initialization.md
@@ -0,0 +1,33 @@
## Initializer settings

The following settings are available for configuration in `config/initializers/devise_token_auth.rb`:

| Name | Default | Description|
|---|---|---|
| **`change_headers_on_each_request`** | `true` | By default the access-token header will change after each request. The client is responsible for keeping track of the changing tokens. Both [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) and [jToker](https://github.com/lynndylanhurley/j-toker) do this out of the box. While this implementation is more secure, it can be difficult to manage. Set this to false to prevent the `access-token` header from changing after each request. [Read more](#about-token-management). |
| **`token_lifespan`** | `2.weeks` | Set the length of your tokens' lifespans. Users will need to re-authenticate after this duration of time has passed since their last login. |
| **`batch_request_buffer_throttle`** | `5.seconds` | Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token. [Read more](#about-batch-requests). |
| **`omniauth_prefix`** | `"/omniauth"` | This route will be the prefix for all oauth2 redirect callbacks. For example, using the default '/omniauth' setting, the github oauth2 provider will redirect successful authentications to '/omniauth/github/callback'. [Read more](#omniauth-provider-settings). |
| **`default_confirm_success_url`** | `nil` | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful email confirmation. If this param is set, the API will redirect to this value when no value is provided by the client. |
| **`default_password_reset_url`** | `nil` | By default this value is expected to be sent by the client so that the API knows where to redirect users after successful password resets. If this param is set, the API will redirect to this value when no value is provided by the client. |
| **`redirect_whitelist`** | `nil` | As an added security measure, you can limit the URLs to which the API will redirect after email token validation (password reset, email confirmation, etc.). This value should be an array containing matches to the client URLs to be visited after validation. Wildcards are supported. |
| **`enable_standard_devise_support`** | `false` | By default, only Bearer Token authentication is implemented out of the box. If, however, you wish to integrate with legacy Devise authentication, you can do so by enabling this flag. NOTE: This feature is highly experimental! |
| **`remove_tokens_after_password_reset`** | `false` | By default, old tokens are not invalidated when password is changed. Enable this option if you want to make passwords updates to logout other devices. |
| **`default_callbacks`** | `true` | By default User model will include the `DeviseTokenAuth::Concerns::UserOmniauthCallbacks` concern, which has `email`, `uid` validations & `uid` synchronization callbacks. |
| **`bypass_sign_in`** | `true` | By default DeviseTokenAuth will not check user's `#active_for_authentication?` which includes confirmation check on each call (it will do it only on sign in). If you want it to be validated on each request (for example, to be able to deactivate logged in users on the fly), set it to false. |


Additionally, you can configure other aspects of devise by manually creating the traditional devise.rb file at `config/initializers/devise.rb`. Here are some examples of what you can do in this file:

~~~ruby
Devise.setup do |config|
# The e-mail address that mail will appear to be sent from
# If absent, mail is sent from "please-change-me-at-config-initializers-devise@example.com"
config.mailer_sender = "support@myapp.com"

# If using rails-api, you may want to tell devise to not use ActionDispatch::Flash
# middleware b/c rails-api does not include it.
# See: https://stackoverflow.com/q/19600905/806956
config.navigational_formats = [:json]
end
~~~
94 changes: 94 additions & 0 deletions docs/config/omniauth.md
@@ -0,0 +1,94 @@
# OmniAuth

## OmniAuth authentication

If you wish to use omniauth authentication, add all of your desired authentication provider gems to your `Gemfile`.

**OmniAuth example using github, facebook, and google**:
~~~ruby
gem 'omniauth-github'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
~~~

Then run `bundle install`.

[List of oauth2 providers](https://github.com/intridea/omniauth/wiki/List-of-Strategies)

## OmniAuth provider settings

In `config/initializers/omniauth.rb`, add the settings for each of your providers.

These settings must be obtained from the providers themselves.

**Example using github, facebook, and google**:
~~~ruby
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: 'email,profile'
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET']
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET']
end
~~~

The above example assumes that your provider keys and secrets are stored in environmental variables. Use the [figaro](https://github.com/laserlemon/figaro) gem (or [dotenv](https://github.com/bkeepers/dotenv) or [secrets.yml](https://github.com/rails/rails/blob/v4.1.0/railties/lib/rails/generators/rails/app/templates/config/secrets.yml) or equivalent) to accomplish this.

#### OmniAuth callback settings

The "Callback URL" setting that you set with your provider must correspond to the [omniauth prefix](initialization.md) setting defined by this app. **This will be different than the omniauth route that is used by your client application**.

For example, the demo app uses the default `omniauth_prefix` setting `/omniauth`, so the "Authorization callback URL" for github must be set to "https://devise-token-auth-demo.herokuapp.com**/omniauth**/github/callback".

**Github example for the demo site**:
![password reset flow](https://github.com/lynndylanhurley/devise_token_auth/raw/master/test/dummy/app/assets/images/omniauth-provider-settings.png)

The url for github authentication will be different for the client. The client should visit the API at `/[MOUNT_PATH]/:provider` for omniauth authentication.

For example, given that the app is mounted using the following settings:

~~~ruby
# config/routes.rb
mount_devise_token_auth_for 'User', at: 'auth'
~~~

The client configuration for github should look like this:

**Angular.js setting for authenticating using github**:
~~~javascript
angular.module('myApp', ['ng-token-auth'])
.config(function($authProvider) {
$authProvider.configure({
apiUrl: 'https://api.example.com'
authProviderPaths: {
github: '/auth/github' // <-- note that this is different than what was set with github
}
});
});
~~~

**jToker settings for github should look like this:

~~~javascript
$.auth.configure({
apiUrl: 'https://api.example.com',
authProviderPaths: {
github: '/auth/github' // <-- note that this is different than what was set with github
}
});
~~~

This incongruence is necessary to support multiple user classes and mounting points.

#### Note for [pow](http://pow.cx/) and [xip.io](http://xip.io) users

If you receive `redirect-uri-mismatch` errors from your provider when using pow or xip.io urls, set the following in your development config:

~~~ruby
# config/environments/development.rb

# when using pow
OmniAuth.config.full_host = "http://app-name.dev"

# when using xip.io
OmniAuth.config.full_host = "http://xxx.xxx.xxx.app-name.xip.io"
~~~

0 comments on commit 23ed467

Please sign in to comment.