Skip to content

Commit

Permalink
Merge pull request #77 from ueberauth/move-token-type-to-typ
Browse files Browse the repository at this point in the history
Move token type to typ
  • Loading branch information
Daniel Neighman committed Dec 28, 2015
2 parents 9d055a7 + e102d28 commit 9994b75
Show file tree
Hide file tree
Showing 18 changed files with 132 additions and 84 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# v 0.9.0

* Remove internal calls to Dict
* Store the type of the token in the typ field rather than the aud field
The aud field should default to the sub or failing that, the iss.
This is to facilitate implementing an OAuth provider or just allowing
folks to declare their own audience.

# v 0.8.1

* Fix a bug with logout where it was not checking the session, only the assigns
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mix.deps
defp deps do
[
# ...
{:guardian, "~> 0.8.1"}
{:guardian, "~> 0.9.0"}
# ...
]
end
Expand Down Expand Up @@ -250,7 +250,7 @@ sockets for e.g. If you need to do things your own way.
```

This will give you a new JWT to use with the claims ready to go.
The token type is encoded into the JWT as the 'aud' field and is intended to be
The token type is encoded into the JWT as the 'typ' field and is intended to be
used as the _type_ of token.

```elixir
Expand All @@ -271,7 +271,7 @@ You can also customize the claims you're asserting.

```elixir
claims = Guardian.Claims.app_claims
|> Dict.put(:some_claim, some_value)
|> Map.put("some_claim", some_value)
|> Guardian.Claims.ttl({3, :days})

{ :ok, jwt, full_claims } = Guardian.encode_and_sign(resource, :token, claims)
Expand Down
34 changes: 19 additions & 15 deletions lib/guardian.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule Guardian do
@default_algos ["HS512"]

if !Application.get_env(:guardian, Guardian), do: raise "Guardian is not configured"
if !Dict.get(Application.get_env(:guardian, Guardian), :serializer), do: raise "Guardian requires a serializer"
if !Keyword.get(Application.get_env(:guardian, Guardian), :serializer), do: raise "Guardian requires a serializer"

@doc """
Encode and sign a JWT from a resource. The resource will be run through the configured serializer to obtain a value suitable for storage inside a JWT.
Expand All @@ -31,15 +31,15 @@ defmodule Guardian do
def encode_and_sign(object), do: encode_and_sign(object, nil, %{})

@doc """
Like encode_and_sign/1 but also accepts the audience (encoded to the aud key) for the JWT
Like encode_and_sign/1 but also accepts the type (encoded to the typ key) for the JWT
The aud can be anything but suggested is "token".
The type can be anything but suggested is "token".
"""
@spec encode_and_sign(any, atom | String.t) :: { :ok, String.t, Map } | { :error, atom } | { :error, String.t }
def encode_and_sign(object, audience), do: encode_and_sign(object, audience, %{})
def encode_and_sign(object, type), do: encode_and_sign(object, type, %{})

@doc false
def encode_and_sign(object, audience, claims) when is_list(claims), do: encode_and_sign(object, audience, Enum.into(claims, %{}))
def encode_and_sign(object, type, claims) when is_list(claims), do: encode_and_sign(object, type, Enum.into(claims, %{}))

@doc """
Like encode_and_sign/2 but also encode anything found inside the claims map into the JWT.
Expand All @@ -51,18 +51,22 @@ defmodule Guardian do
Guardian.encode_and_sign(user, :token, perms: %{ default: [:read, :write] })
"""
@spec encode_and_sign(any, atom | String.t, Map) :: { :ok, String.t, Map } | { :error, atom } | { :error, String.t }
def encode_and_sign(object, audience, claims) do
def encode_and_sign(object, type, claims) do
claims = stringify_keys(claims)
perms = Dict.get(claims, "perms", %{})
claims = Guardian.Claims.permissions(claims, perms) |> Dict.delete("perms")
perms = Map.get(claims, "perms", %{})
claims = Guardian.Claims.permissions(claims, perms) |> Map.delete("perms")

case Guardian.serializer.for_token(object) do
{ :ok, sub } ->
full_claims = Guardian.Claims.app_claims(claims)
|> Guardian.Claims.aud(audience)
|> Guardian.Claims.typ(type)
|> Guardian.Claims.sub(sub)

case Guardian.hooks_module.before_encode_and_sign(object, audience, full_claims) do
if Map.get(full_claims, "aud") == nil do
full_claims = Guardian.Claims.aud(full_claims, sub)
end

case Guardian.hooks_module.before_encode_and_sign(object, type, full_claims) do
{ :error, reason } -> { :error, reason }
{ :ok, { resource, type, hooked_claims } } ->
case encode_claims(hooked_claims) do
Expand Down Expand Up @@ -139,11 +143,11 @@ defmodule Guardian do
|> Guardian.Claims.iat
|> Guardian.Claims.ttl

aud = Map.get(new_claims, "aud")
type = Map.get(new_claims, "typ")

{:ok, resource} = Guardian.serializer.from_token(Map.get(new_claims, "sub"))

case encode_and_sign(resource, aud, new_claims) do
case encode_and_sign(resource, type, new_claims) do
{:ok, jwt, full_claims} ->
revoke!(jwt, claims)
{:ok, jwt, full_claims}
Expand All @@ -170,7 +174,7 @@ defmodule Guardian do
@spec decode_and_verify(String.t, Map) :: { :ok, Map } | { :error, atom | String.t }
def decode_and_verify(jwt, params) do
params = stringify_keys(params)
if verify_issuer?, do: params = Dict.put_new(params, "iss", issuer)
if verify_issuer?, do: params = Map.put_new(params, "iss", issuer)
params = stringify_keys(params)

try do
Expand Down Expand Up @@ -220,9 +224,9 @@ defmodule Guardian do
@doc false
def config, do: Application.get_env(:guardian, Guardian)
@doc false
def config(key), do: Dict.get(config, key)
def config(key), do: Keyword.get(config, key)
@doc false
def config(key, default), do: Dict.get(config, key, default)
def config(key, default), do: Keyword.get(config, key, default)

defp jose_jws do
%{ "alg" => hd(allowed_algos) }
Expand Down
4 changes: 2 additions & 2 deletions lib/guardian/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ defmodule Guardian.Channel do
"""
defmacro __using__(opts) do
opts = Enum.into(opts, %{})
key = Dict.get(opts, :key, :default)
key = Map.get(opts, :key, :default)

quote do
def join(room, auth = %{ "guardian_token" => jwt }, socket) do
Expand All @@ -48,7 +48,7 @@ defmodule Guardian.Channel do
defp handle_guardian_join(room, jwt, params, socket) do
case Guardian.decode_and_verify(jwt, params) do
{ :ok, claims } ->
case Guardian.serializer.from_token(Dict.get(claims, "sub")) do
case Guardian.serializer.from_token(Map.get(claims, "sub")) do
{ :ok, resource } ->
authed_socket = socket
|> assign(Guardian.Keys.claims_key(unquote(key)), claims)
Expand Down
24 changes: 17 additions & 7 deletions lib/guardian/claim_valiation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ defmodule Guardian.ClaimValidation do
def validate_claim("iss", payload, _) do
verify_issuer = Guardian.config(:verify_issuer, false)
if verify_issuer do
if Dict.get(payload, "iss") == Guardian.config(:issuer), do: :ok, else: { :error, :invalid_issuer }
if Map.get(payload, "iss") == Guardian.config(:issuer), do: :ok, else: { :error, :invalid_issuer }
else
:ok
end
end

def validate_claim(:nbf, payload, opts), do: validate_claim("nbf", payload, opts)
def validate_claim("nbf", payload, _) do
case Dict.get(payload, "nbf") do
case Map.get(payload, "nbf") do
nil -> :ok
nbf -> if nbf > Guardian.Utils.timestamp, do: { :error, :token_not_yet_valid }, else: :ok
end
end

def validate_claim(:iat, payload, opts), do: validate_claim("iat", payload, opts)
def validate_claim("iat", payload, _) do
case Dict.get(payload, "iat") do
case Map.get(payload, "iat") do
nil -> :ok
iat -> if iat > Guardian.Utils.timestamp, do: { :error, :token_not_yet_valid }, else: :ok
end
Expand All @@ -34,16 +34,26 @@ defmodule Guardian.ClaimValidation do
def validate_claim(:exp, payload, opts), do: validate_claim("exp", payload, opts)
def validate_claim("exp", payload, _) do

case Dict.get(payload, "exp") do
case Map.get(payload, "exp") do
nil -> :ok
_ -> if Dict.get(payload, "exp") < Guardian.Utils.timestamp, do: { :error, :token_expired }, else: :ok
_ -> if Map.get(payload, "exp") < Guardian.Utils.timestamp, do: { :error, :token_expired }, else: :ok
end
end

def validate_claim(:typ, payload, opts), do: validate_claim("typ", payload, opts)
def validate_claim("typ", payload, opts) do
has_typ_key? = Map.has_key?(opts, "typ")
if has_typ_key? and Map.get(opts, "typ") != Map.get(payload, "typ") do
{ :error, :invalid_type }
else
:ok
end
end

def validate_claim(:aud, payload, opts), do: validate_claim("aud", payload, opts)
def validate_claim("aud", payload, opts) do
has_aud_key? = Dict.has_key?(opts, "aud")
if has_aud_key? and Dict.get(opts, "aud") != Dict.get(payload, "aud") do
has_aud_key? = Map.has_key?(opts, "aud")
if has_aud_key? and Map.get(opts, "aud") != Map.get(payload, "aud") do
{ :error, :invalid_audience }
else
:ok
Expand Down
9 changes: 8 additions & 1 deletion lib/guardian/claims.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ defmodule Guardian.Claims do
end

@doc false
def aud(claims, nil), do: aud(claims, "token")
def typ(claims, nil), do: typ(claims, "token")
@doc false
def typ(claims, type) when is_atom(type), do: typ(claims, to_string(type))
@doc false
def typ(claims, type), do: Map.put(claims, "typ", type)

@doc false
def aud(claims, nil), do: aud(claims, Guardian.config(:issuer))
@doc false
def aud(claims, audience) when is_atom(audience), do: aud(claims, to_string(audience))
@doc false
Expand Down
16 changes: 8 additions & 8 deletions lib/guardian/permissions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ defmodule Guardian.Permissions do

expanded_perms = Enum.reduce(perms, %{}, fn({key, values}, acc) ->
perms_as_values = Enum.with_index(values) |> Enum.reduce(%{}, fn({ name, idx}, acc) ->
Dict.put(acc, name, trunc(:math.pow(2,idx)))
Map.put(acc, name, trunc(:math.pow(2,idx)))
end)

Dict.put(acc, key, perms_as_values)
Map.put(acc, key, perms_as_values)
end)

Enum.map(expanded_perms, fn({type, values}) ->
Expand Down Expand Up @@ -124,13 +124,13 @@ defmodule Guardian.Permissions do
end)

def from_claims(claims, unquote(type)) do
c = Dict.get(claims, "pem", %{})
Dict.get(c, unquote(type), Dict.get(c, unquote(to_string(type)), 0))
c = Map.get(claims, "pem", %{})
Map.get(c, unquote(type), Map.get(c, unquote(to_string(type)), 0))
end

def from_claims(claims, unquote(to_string(type))) do
c = Dict.get(claims, "pem", %{})
Dict.get(c, unquote(type), Dict.get(c, unquote(to_string(type)), 0))
c = Map.get(claims, "pem", %{})
Map.get(c, unquote(type), Map.get(c, unquote(to_string(type)), 0))
end
end)

Expand All @@ -140,13 +140,13 @@ defmodule Guardian.Permissions do
Fetches the list of known permissions for the given type
"""
@spec available(atom) :: List
def available(type), do: Dict.get(@perms, type, [])
def available(type), do: Map.get(@perms, type, [])

@doc """
Fetches the list of known permissions for the default type
"""
@spec available :: List
def available, do: Dict.get(@perms, :default, [])
def available, do: Map.get(@perms, :default, [])


def all?(value, expected, key \\ :default) do
Expand Down
8 changes: 4 additions & 4 deletions lib/guardian/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ defmodule Guardian.Plug do
"""
@spec sign_in(Plug.Conn.t, any, atom | String.t, Map) :: Plug.Conn.t
def sign_in(conn, object, type, claims) do
the_key = Dict.get(claims, :key, :default)
claims = Dict.delete(claims, :key)
the_key = Map.get(claims, :key, :default)
claims = Map.delete(claims, :key)

case Guardian.encode_and_sign(object, type, claims) do
{ :ok, jwt, full_claims } ->
Expand Down Expand Up @@ -125,8 +125,8 @@ defmodule Guardian.Plug do
"""
@spec api_sign_in(Plug.Conn.t, any, atom | String.t, Map) :: Plug.Conn.t
def api_sign_in(conn, object, type, claims) do
the_key = Dict.get(claims, :key, :default)
claims = Dict.delete(claims, :key)
the_key = Map.get(claims, :key, :default)
claims = Map.delete(claims, :key)

case Guardian.encode_and_sign(object, type, claims) do
{ :ok, jwt, full_claims } ->
Expand Down
10 changes: 5 additions & 5 deletions lib/guardian/plug/ensure_permissions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ defmodule Guardian.Plug.EnsurePermissions do
%{
handler: handler,
key: key,
perm_keys: Dict.keys(perms),
perm_keys: Map.keys(perms),
perms: perms,
}
end

@doc false
def call(conn, opts) do
key = Dict.get(opts, :key)
key = Map.get(opts, :key)
case Guardian.Plug.claims(conn, key) do
{ :ok, claims } ->
perms = Dict.get(opts, :perms, %{})
result = Enum.all?(Dict.get(opts, :perm_keys), fn(perm_key) ->
perms = Map.get(opts, :perms, %{})
result = Enum.all?(Map.get(opts, :perm_keys), fn(perm_key) ->
found_perms = Guardian.Permissions.from_claims(claims, perm_key)
Guardian.Permissions.all?(found_perms, Dict.get(perms, perm_key), perm_key)
Guardian.Permissions.all?(found_perms, Map.get(perms, perm_key), perm_key)
end)
if result, do: conn, else: handle_error(conn, opts)
{ :error, _ } -> handle_error(conn, opts)
Expand Down
4 changes: 2 additions & 2 deletions lib/guardian/plug/load_resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ defmodule Guardian.Plug.LoadResource do

@doc false
def call(conn, opts) do
key = Dict.get(opts, :key, :default)
key = Map.get(opts, :key, :default)

case Guardian.Plug.current_resource(conn, key) do
{ :ok, _ } -> conn
{ :error, _ } -> conn
_ ->
case Guardian.Plug.claims(conn, key) do
{ :ok, claims } ->
case Guardian.serializer.from_token(Dict.get(claims, "sub")) do
case Guardian.serializer.from_token(Map.get(claims, "sub")) do
{ :ok, resource } -> Guardian.Plug.set_current_resource(conn, resource, key)
{ :error, _ } -> Guardian.Plug.set_current_resource(conn, nil, key)
end
Expand Down
6 changes: 3 additions & 3 deletions lib/guardian/plug/verify_header.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ defmodule Guardian.Plug.VerifyHeader do

def init(opts \\ %{}) do
opts_map = Enum.into(opts, %{})
realm = Dict.get(opts_map, :realm)
realm = Map.get(opts_map, :realm)
if realm do
{ :ok, reg } = Regex.compile("#{realm}\:?\s+(.*)$", "i")
opts_map = Dict.put(opts_map, :realm_reg, reg)
opts_map = Map.put(opts_map, :realm_reg, reg)
end
opts_map
end

def call(conn, opts) do
key = Dict.get(opts, :key, :default)
key = Map.get(opts, :key, :default)

case Guardian.Plug.claims(conn, key) do
{ :ok, _ } -> conn
Expand Down
2 changes: 1 addition & 1 deletion lib/guardian/plug/verify_session.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Guardian.Plug.VerifySession do

@doc false
def call(conn, opts) do
key = Dict.get(opts, :key, :default)
key = Map.get(opts, :key, :default)

case Guardian.Plug.claims(conn, key) do
{ :ok, _ } -> conn
Expand Down
2 changes: 1 addition & 1 deletion lib/guardian/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Guardian.Utils do
@doc false
def stringify_keys(nil), do: %{}
def stringify_keys(map) do
Enum.reduce(Dict.keys(map), %{}, fn(k,acc) -> Dict.put(acc, to_string(k), map[k]) end)
Enum.reduce(Map.keys(map), %{}, fn(k,acc) -> Map.put(acc, to_string(k), map[k]) end)
end

@doc false
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Guardian.Mixfile do
use Mix.Project

@version "0.8.1"
@version "0.9.0"
@url "https://github.com/ueberauth/guardian"
@maintainers ["Daniel Neighman", "Sonny Scroggin", "Sean Callan"]

Expand Down
Loading

0 comments on commit 9994b75

Please sign in to comment.