Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move code.ensure_loaded #663

Merged
merged 1 commit into from
Sep 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 78 additions & 78 deletions lib/guardian/plug/pipeline.ex
Original file line number Diff line number Diff line change
@@ -1,112 +1,111 @@
defmodule Guardian.Plug.Pipeline do
@moduledoc """
Helps to build plug pipelines for use with Guardian and associated plugs.
if Code.ensure_loaded?(Plug) do
defmodule Guardian.Plug.Pipeline do
@moduledoc """
Helps to build plug pipelines for use with Guardian and associated plugs.

All Guardian provided plugs have a number of features.
All Guardian provided plugs have a number of features.

1. They take a `:key` option to know where to store information in the session and connection
2. They require a reference to the implementation (the module that `use Guardian`)
3. They require a reference to an error handling module
1. They take a `:key` option to know where to store information in the session and connection
2. They require a reference to the implementation (the module that `use Guardian`)
3. They require a reference to an error handling module

These references are passed through the connection so they must be put in place
before the Guardian Plugs. By using a pipeline this is taken care of for you.
These references are passed through the connection so they must be put in place
before the Guardian Plugs. By using a pipeline this is taken care of for you.

The easiest way to use `Guardian.Plug.Pipeline` is to create a module that defines your pipeline.
The easiest way to use `Guardian.Plug.Pipeline` is to create a module that defines your pipeline.

```elixir
defmodule MyApp.AuthPipeline do
use Guardian.Plug.Pipeline, otp_app: :my_app,
module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
```elixir
defmodule MyApp.AuthPipeline do
use Guardian.Plug.Pipeline, otp_app: :my_app,
module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler

@claims %{iss: "IssuerApp"}
@claims %{iss: "IssuerApp"}

plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: true
end
```
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: true
end
```

When you want to use the pipeline you just use it like a normal plug.
When you want to use the pipeline you just use it like a normal plug.

```elixir
plug MyApp.AuthPipeline
```
```elixir
plug MyApp.AuthPipeline
```

This pipeline will look for tokens in either the session (it's ok if it's not loaded)
followed by the header if one wasn't found in the session.
This pipeline will look for tokens in either the session (it's ok if it's not loaded)
followed by the header if one wasn't found in the session.

We then ensure that we found a token and fail if not.
We then ensure that we found a token and fail if not.

Given that we found a token, we then attempt to load the resource the token
refers to, failing if one is not found.
Given that we found a token, we then attempt to load the resource the token
refers to, failing if one is not found.

### Customizing your pipeline
### Customizing your pipeline

Once you've created a pipeline, you can customize it when you call it with options.
Once you've created a pipeline, you can customize it when you call it with options.

```elixir
plug MyApp.AuthPipeline, module: MyApp.ADifferentGuardianModule
# OR
plug MyApp.AuthPipeline, key: :impersonate
```
```elixir
plug MyApp.AuthPipeline, module: MyApp.ADifferentGuardianModule
# OR
plug MyApp.AuthPipeline, key: :impersonate
```

### Options
### Options

You can provide options to the pipeline when you `use Guardian.Plug.Pipeline`
or you can provide them when you call the plug.
You can provide options to the pipeline when you `use Guardian.Plug.Pipeline`
or you can provide them when you call the plug.

Additionally, for every option other than `:otp_app` you can use elixir
configuration, the `use` options, or inline options.
Additionally, for every option other than `:otp_app` you can use elixir
configuration, the `use` options, or inline options.

* `:otp_app` - The otp app where the pipeline modules can be found
* `:module` - The `Guardian` implementation module
* `:error_handler` - The error handler module
* `:key` - The key to use
* `:otp_app` - The otp app where the pipeline modules can be found
* `:module` - The `Guardian` implementation module
* `:error_handler` - The error handler module
* `:key` - The key to use

### Keys
### Keys

Using keys allows you to specifiy locations in the session/connection where
the tokens and resources will be placed. This allows multiple authenticated
tokens to be in play for a single request. This is useful for impersonation or
higher security areas where you can have a specific set of privileges and
still be logged in.
Using keys allows you to specifiy locations in the session/connection where
the tokens and resources will be placed. This allows multiple authenticated
tokens to be in play for a single request. This is useful for impersonation or
higher security areas where you can have a specific set of privileges and
still be logged in.

### Error handler
### Error handler

When using plugs, you'll need to specify an error handler module
When using plugs, you'll need to specify an error handler module

See `Guardian.Plug.ErrorHandler` documentation for more details.
See `Guardian.Plug.ErrorHandler` documentation for more details.

### Inline pipelines
### Inline pipelines

If you want to define your pipeline inline, you can do so by using
`Guardian.Plug.Pipeline` as a plug itself.
You _must_ supply the module and error handler inline if you do this.
If you want to define your pipeline inline, you can do so by using
`Guardian.Plug.Pipeline` as a plug itself.
You _must_ supply the module and error handler inline if you do this.

```elixir
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"
```
```elixir
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"
```

Inline pipelines are also good to change the error handler that you want to use.
Inline pipelines are also good to change the error handler that you want to use.

Note that you must set the pipeline before using other guardian plugs.
Note that you must set the pipeline before using other guardian plugs.

```elixir
# Use the MyApp.AuthErrorHandler for downstream Guardian plugs
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"
```elixir
# Use the MyApp.AuthErrorHandler for downstream Guardian plugs
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"

# Now change out the error handler for plugs downstream of this one.
plug Guardian.Plug.Pipeline, error_handler: MyApp.SpecialAuthErrorHandler
```
"""
if Code.ensure_loaded?(Plug) do
import Plug.Conn
# Now change out the error handler for plugs downstream of this one.
plug Guardian.Plug.Pipeline, error_handler: MyApp.SpecialAuthErrorHandler
```
"""

@doc """
Create your very own `Guardian.Plug.Pipeline`
Expand Down Expand Up @@ -171,6 +170,7 @@ defmodule Guardian.Plug.Pipeline do
end
end

import Plug.Conn
@behaviour Plug

@impl Plug
Expand Down