Packages

Magic admin Elixir SDK makes it easy to leverage Decentralized ID tokens to protect routes and restricted resources for your application.

Current section

Files

Jump to
magic_admin lib token.ex
Raw

lib/token.ex

defmodule Magic.Token do
@moduledoc """
Provides methods to interact with the DID Token.
"""
@nbf_grace_period 300
alias Magic.Utils
alias Magic.DIDTokenError
@doc """
Description:
Method validate did_token
Arguments:
did_token: A DID Token generated by a Magic user on the client-side.
Returns:
true or raise an error
"""
def validate!(did_token) do
time = DateTime.utc_now() |> DateTime.to_unix()
%{proof: proof, claim: claim, message: message} = decode!(did_token)
rec_address = recover_address(proof, message)
validate_public_address!(rec_address, did_token)
validate_claim_fields!(claim)
validate_claim_ext!(time, claim["ext"])
validate_claim_nbf!(time, claim["nbf"])
true
end
@doc """
Description:
Method Decodes a DID Token from a Base64 string into
a tuple of its individual components: proof and claim.
This method allows you decode the DID Token
and inspect the token
Arguments:
did_token: A DID Token generated by a Magic user on the client-side.
Returns:
A map containing proof, claim and message or raise an error
"""
def decode!(did_token) do
try do
[proof, message] = Base.decode64!(did_token) |> Jason.decode!()
claim = Jason.decode!(message)
validate_claim_fields!(claim)
%{proof: proof, claim: claim, message: message}
rescue
ArgumentError -> raise DIDTokenError, message: "DID Token is malformed"
Jason.DecodeError -> raise DIDTokenError, message: "DID Token is malformed"
end
end
@doc """
Description:
Method parse public_address and extract issuer
Arguments:
public_address: Cryptographic public address of the Magic User.
Returns:
issuer info
"""
def construct_issuer_with_public_address(public_address) do
"did:ethr:#{public_address}"
end
@doc """
Description:
Method parse did_token and extract issuer
Arguments:
did_token: A DID Token generated by a Magic user on the client-side.
Returns:
issuer info
"""
def get_issuer(did_token) do
%{claim: claim} = decode!(did_token)
claim["iss"]
end
@doc """
Description:
Method parse did_token and extract cryptographic public_address
Arguments:
did_token: A DID Token generated by a Magic user on the client-side.
Returns:
cryptographic public address of the Magic User
who generated the supplied DID Token.
"""
def get_public_address(did_token) do
get_issuer(did_token) |> String.split(":") |> List.last()
end
defp recover_address(proof, message) do
Utils.recover_pubkey(message, proof) |> Utils.pubkey_to_address()
end
defp claim_fields() do
~w(iat ext iss sub aud nbf tid)
end
defp validate_claim_fields!(claim) do
missing_fields = claim_fields() -- Map.keys(claim)
if length(missing_fields) > 0 do
raise DIDTokenError,
message: "DID Token missing required fields: #{Enum.join(missing_fields, ", ")}"
end
end
defp validate_public_address!(rec_address, did_token) do
if Utils.hex_to_bin(rec_address) != Utils.hex_to_bin(get_public_address(did_token)) do
message = "Signature mismatch between 'proof' and 'claim'."
raise DIDTokenError, message: message
end
end
defp validate_claim_ext!(time, claim_ext) do
if time > claim_ext do
message = "Given DID token has expired. Please generate a new one."
raise DIDTokenError, message: message
end
end
defp apply_nbf_grace_period(claim_nbf) do
claim_nbf - @nbf_grace_period
end
defp validate_claim_nbf!(time, claim_nbf) do
if time < apply_nbf_grace_period(claim_nbf) do
message = "Given DID token cannot be used at this time."
raise DIDTokenError, message: message
end
end
end