Skip to content

Commit

Permalink
Add scheme option to VerifyHeader
Browse files Browse the repository at this point in the history
closes #464
  • Loading branch information
yordis committed Jul 17, 2021
1 parent 11bd017 commit 6a77cae
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 22 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog

## v2.2.0
### Enhancement

* Add `:scheme` option to `Guardian.Plug.VerifyHeader`

### Deprecation

* `:scheme` option configuration of `Guardian.Plug.VerifyHeader` is deprecated
please use `:scheme` instead.
## v2.1.2
### Enhancement
* Documentation improvements
Expand Down
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -434,7 +434,8 @@ For more in-depth documentation please see the [GuardianDb README](https://githu

### How to add the token to a request (the Phoenix way)

Assuming you are using the default realm `Bearer` for the `Authorization` header:
Assuming you are using the default authentication scheme `Bearer` for
the `Authorization` header:

```elixir
defmodule HelloWeb.AuthControllerTest do
Expand Down
6 changes: 3 additions & 3 deletions lib/guardian/plug/pipeline.ex
Expand Up @@ -23,7 +23,7 @@ if Code.ensure_loaded?(Plug) do
@claims %{iss: "IssuerApp"}
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.VerifyHeader, claims: @claims, scheme: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: true
end
Expand Down Expand Up @@ -90,7 +90,7 @@ if Code.ensure_loaded?(Plug) do
```elixir
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"
plug Guardian.VerifyHeader, scheme: "Bearer"
```
Inline pipelines are also good to change the error handler that you want to use.
Expand All @@ -101,7 +101,7 @@ if Code.ensure_loaded?(Plug) do
# Use the MyApp.AuthErrorHandler for downstream Guardian plugs
plug Guardian.Plug.Pipeline, module: MyApp.Tokens,
error_handler: MyApp.AuthErrorHandler
plug Guardian.VerifyHeader, realm: "Bearer"
plug Guardian.VerifyHeader, scheme: "Bearer"
# Now change out the error handler for plugs downstream of this one.
plug Guardian.Plug.Pipeline, error_handler: MyApp.SpecialAuthErrorHandler
Expand Down
42 changes: 27 additions & 15 deletions lib/guardian/plug/verify_header.ex
Expand Up @@ -32,7 +32,7 @@ if Code.ensure_loaded?(Plug) do
* `claims` - The literal claims to check to ensure that a token is valid
* `max_age` - If the token has an "auth_time" claim, check it is not older than the maximum age.
* `header_name` - The name of the header to search for a token. Defaults to `authorization`.
* `realm` - The prefix for the token in the header. Defaults to `Bearer`.
* `scheme` - The prefix for the token in the header. Defaults to `Bearer`.
`:none` will not use a prefix.
* `key` - The location to store the information in the connection. Defaults to: `default`
* `halt` - Whether to halt the connection in case of error. Defaults to `true`.
Expand Down Expand Up @@ -76,19 +76,9 @@ if Code.ensure_loaded?(Plug) do
@impl Plug
@spec init(opts :: Keyword.t()) :: Keyword.t()
def init(opts \\ []) do
realm = Keyword.get(opts, :realm, "Bearer")

case realm do
"" ->
opts

:none ->
opts

_realm ->
{:ok, reg} = Regex.compile("#{realm}\:?\s+(.*)$", "i")
Keyword.put(opts, :realm_reg, reg)
end
opts
|> get_scheme()
|> put_scheme_reg(opts)
end

@impl Plug
Expand All @@ -115,6 +105,28 @@ if Code.ensure_loaded?(Plug) do
end
end

defp put_scheme_reg("", opts) do
opts
end

defp put_scheme_reg(:none, opts) do
opts
end

defp put_scheme_reg(scheme, opts) do
{:ok, reg} = Regex.compile("#{scheme}\:?\s+(.*)$", "i")
Keyword.put(opts, :scheme_reg, reg)
end

defp get_scheme(opts) do
if Keyword.has_key?(opts, :realm) do
IO.warn("`:realm` option is deprecated; please rename `:realm` to `:scheme` option instead.")
Keyword.get(opts, :realm, "Bearer")
else
Keyword.get(opts, :scheme, "Bearer")
end
end

defp handle_error(conn, :token_expired = reason, opts) do
if refresh_from_cookie_opts = fetch_refresh_from_cookie_options(opts) do
Guardian.Plug.VerifyCookie.refresh_from_cookie(conn, refresh_from_cookie_opts)
Expand Down Expand Up @@ -157,7 +169,7 @@ if Code.ensure_loaded?(Plug) do
defp fetch_token_from_header(_, _, []), do: :no_token_found

defp fetch_token_from_header(conn, opts, [token | tail]) do
reg = Keyword.get(opts, :realm_reg, ~r/^(.*)$/)
reg = Keyword.get(opts, :scheme_reg, ~r/^(.*)$/)
trimmed_token = String.trim(token)

case Regex.run(reg, trimmed_token) do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Expand Up @@ -2,7 +2,7 @@ defmodule Guardian.Mixfile do
@moduledoc false
use Mix.Project

@version "2.1.2"
@version "2.2.0"
@url "https://github.com/ueberauth/guardian"
@maintainers [
"Daniel Neighman",
Expand Down
22 changes: 20 additions & 2 deletions test/guardian/plug/verify_header_test.exs
Expand Up @@ -2,12 +2,13 @@ defmodule Guardian.Plug.VerifyHeaderTest do
@moduledoc false

use Plug.Test
use ExUnit.Case, async: true

import ExUnit.CaptureIO

alias Guardian.Plug.Pipeline
alias Guardian.Plug.VerifyHeader

use ExUnit.Case, async: true

defmodule Handler do
@moduledoc false

Expand Down Expand Up @@ -116,6 +117,23 @@ defmodule Guardian.Plug.VerifyHeaderTest do
assert Guardian.Plug.current_claims(conn, key: :secret) == ctx.claims
end

test "with :realm option shows a warning message" do
has_warning_message =
:stderr
|> capture_io(fn -> VerifyHeader.init(realm: "Bearer") end)
|> String.contains?("`:realm` option is deprecated; please rename `:realm` to `:scheme` option instead.")

assert has_warning_message
end

test "getting the scheme config" do
opts = VerifyHeader.init(realm: "Bearer")
assert opts[:scheme_reg] == ~r/Bearer:? +(.*)$/i

opts = VerifyHeader.init(scheme: "Basic")
assert opts[:scheme_reg] == ~r/Basic:? +(.*)$/i
end

test "with a token and mismatching claims", ctx do
conn =
:get
Expand Down

0 comments on commit 6a77cae

Please sign in to comment.