View Source AppIdentity (AppIdentity for Elixir v1.2.0)
AppIdentity
is an Elixir implementation of the Kinetic Commerce application
identity proof algorithm.
It implements identity proof generation and validation functions. These
functions expect to work with an application structure
(AppIdentity.App.t/0
).
telemetry-support
Telemetry Support
If telemetry is a dependency in your
application, and the telemetry is not explicitly disabled, telemetry events
will be emitted for AppIdentity.generate_proof/2
,
AppIdentity.verify_proof/3
, and AppIdentity.Plug
. See
AppIdentity.Telemetry
for more information.
disabling-telemetry
Disabling Telemetry
Telemetry may be disabled by setting this for your configuration:
config :app_identity, AppIdentity.Telemetry, enabled: false
Remember to run mix deps.compile --force tesla
after changing this setting
to ensure the change is picked up.
Link to this section Summary
Types
A list of algorithm versions that are not allowed.
The App Identity app unique identifier. Validation of the id
value will
convert non-string IDs using Kernel.to_string/1.
A nonce value used in the algorithm proof. The shape of the nonce depends on
the algorithm version/0
.
Options for generating or verifying proofs.
The App Identity app secret value. This value is used as provided with no encoding or decoding. Because this is a sensitive value, it may be provided as a closure in line with the EEF Security Working Group sensitive data recommendation.
The positive integer version of the App Identity algorithm to use. Will be validated to be a supported version for app creation, and not an explicitly disallowed version during proof validation.
Functions
Generate an identity proof string for the given application. Returns {:ok, proof}
or :error
.
Generate an identity proof string for the given application. Returns the proof string or raises an exception on error.
The name, version, and supported specification version of this App Identity package for Elixir.
The name, version, or supported specification version of this App Identity package for Elixir.
Parses a proof string into an AppIdentity.Proof struct. Returns {:ok, proof}
or :error
.
Parses a proof string into an AppIdentity.Proof struct. Returns the parsed proof or raises an exception.
Verify a AppIdentity
proof value using a a provided app
. Returns {:ok, app}
, {:ok, nil}
, or :error
.
Verify a AppIdentity
proof value using a a provided app
. Returns the app,
nil, or raises an exception on error.
Link to this section Types
@type disallowed() :: {:disallowed, [version()]}
A list of algorithm versions that are not allowed.
The presence of an app in this list will prevent the generation or verification of proofs for the specified version.
If nil
, an empty list, or missing, all versions are allowed.
@type id() :: binary()
The App Identity app unique identifier. Validation of the id
value will
convert non-string IDs using Kernel.to_string/1.
If using integer IDs, it is recommended that the id
value be provided as
some form of extended string value, such as that provided by Rails global
ID or the absinthe_relay
Node.IDTranslator.
Such representations are also recommended if the ID is a compound value.
id/0
values must not contain a colon (:
) character.
@type nonce() :: String.t()
A nonce value used in the algorithm proof. The shape of the nonce depends on
the algorithm version/0
.
Version 1 nonce/0
values should be cryptographically secure and
non-sequential, but sufficiently fine-grained timestamps (those including
microseconds, as yyyymmddHHMMSS.sss
) may be used. Version 1 proofs verify
that the nonce is at least one byte long and do not contain a colon (:
).
Version 2, 3, and 4 nonce/0
values only permit fine-grained timestamps
that should be generated from a clock in sync with Network Time Protocol
servers. The timestamp will be parsed and compared to the server time (also in
sync with an NTP server).
@type option() :: disallowed() | {:nonce, nonce()} | {:version, version()}
Options for generating or verifying proofs.
nonce
can specify a precomputed nonce for proof generation. It will be verified by the algorithm version for correctness and compatibility, but will otherwise be used unmodified. This option is ignored for proof verification.version
can specify the generation of a proof compatible with, but different than, the application version. This option is ignored for proof verification.
@type secret() :: binary()
The App Identity app secret value. This value is used as provided with no encoding or decoding. Because this is a sensitive value, it may be provided as a closure in line with the EEF Security Working Group sensitive data recommendation.
AppIdentity.App
always stores this value as a closure.
@type version() :: pos_integer()
The positive integer version of the App Identity algorithm to use. Will be validated to be a supported version for app creation, and not an explicitly disallowed version during proof validation.
If provided as a string value, it must convert cleanly to an integer value,
which means that a version of "3.5"
is not a valid value.
App Identity algorithm versions are strictly upgradeable. That is, a version 1 app can verify version 1, 2, 3, or 4 proofs. However, a version 2 app will never validate a version 1 proof.
App Identity Version |
Nonce | Digest Algorithm | Can Verify Proof from Version |
|||
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
1 | random | SHA2-256 | Yes | Yes | Yes | Yes |
2 | timestamp ± fuzz | SHA2-256 | - | Yes | Yes | Yes |
3 | timestamp ± fuzz | SHA2-384 | - | - | Yes | Yes |
4 | timestamp ± fuzz | SHA2-512 | - | - | - | Yes |
Link to this section Functions
@spec generate_proof( AppIdentity.App.t() | AppIdentity.App.loader() | AppIdentity.App.t(), [option()] ) :: {:ok, String.t()} | :error
Generate an identity proof string for the given application. Returns {:ok, proof}
or :error
.
If nonce
is provided, it must conform to the shape expected by the proof
version. If not provided, it will be generated.
If version
is provided, it will be used to generate the nonce and the proof.
This will allow a lower level application to raise its version level.
examples
Examples
A version 1 app can have a fixed nonce, which will always produce the same value.
iex> {:ok, app} = AppIdentity.App.new(%{version: 1, id: "decaf", secret: "bad"})
iex> AppIdentity.generate_proof(app, nonce: "hello")
{:ok, "ZGVjYWY6aGVsbG86RDNGNjJCQTYyOEIyMzhEOTgwM0MyNEU4NkNCOTY3M0ZEOTVCNTdBNkJGOTRFMkQ2NTMxQTRBODg1OTlCMzgzNQ=="}
A version 2 app fails when given a non-timestamp nonce.
iex> AppIdentity.generate_proof(v1(), version: 2, nonce: "hello")
:error
A version 2 app cannot generate a version 1 nonce.
iex> AppIdentity.generate_proof(v2(), version: 1)
:error
A version 2 app will be rejected if the version has been disallowed.
iex> AppIdentity.generate_proof(v2(), disallowed: [1, 2])
:error
telemetry
Telemetry
When telemetry is enabled, generate_proof/2
will emit:
[:app_identity, :generate_proof, :start]
[:app_identity, :generate_proof, :stop]
@spec generate_proof!( AppIdentity.App.t() | AppIdentity.App.loader() | AppIdentity.App.t(), [option()] ) :: String.t()
Generate an identity proof string for the given application. Returns the proof string or raises an exception on error.
If nonce
is provided, it must conform to the shape expected by the proof
version. If not provided, it will be generated.
If version
is provided, it will be used to generate the nonce and the proof.
This will allow a lower level application to raise its version level.
examples
Examples
A version 1 app can have a fixed nonce, which will always produce the same value.
iex> {:ok, app} = AppIdentity.App.new(%{version: 1, id: "decaf", secret: "bad"})
iex> AppIdentity.generate_proof!(app, nonce: "hello")
"ZGVjYWY6aGVsbG86RDNGNjJCQTYyOEIyMzhEOTgwM0MyNEU4NkNCOTY3M0ZEOTVCNTdBNkJGOTRFMkQ2NTMxQTRBODg1OTlCMzgzNQ=="
A version 2 app fails when given a non-timestamp nonce.
iex> AppIdentity.generate_proof!(v1(), version: 2, nonce: "hello")
** (AppIdentity.AppIdentityError) Error generating proof
A version 2 app cannot generate a version 1 nonce.
iex> AppIdentity.generate_proof!(v2(), version: 1)
** (AppIdentity.AppIdentityError) Error generating proof
A version 2 app will be rejected if the version has been disallowed.
iex> AppIdentity.generate_proof!(v2(), disallowed: [1, 2])
** (AppIdentity.AppIdentityError) Error generating proof
telemetry
Telemetry
When telemetry is enabled, generate_proof!/2
will emit:
[:app_identity, :generate_proof, :start]
[:app_identity, :generate_proof, :stop]
Telemetry events are emitted before any error exceptions are thrown.
@spec info() :: %{name: String.t(), version: String.t(), spec_version: pos_integer()}
The name, version, and supported specification version of this App Identity package for Elixir.
@spec info(:name | :spec_version | :version) :: String.t() | pos_integer()
The name, version, or supported specification version of this App Identity package for Elixir.
@spec parse_proof(AppIdentity.Proof.t() | String.t()) :: {:ok, AppIdentity.Proof.t()} | :error
Parses a proof string into an AppIdentity.Proof struct. Returns {:ok, proof}
or :error
.
@spec parse_proof!(AppIdentity.Proof.t() | String.t()) :: AppIdentity.Proof.t()
Parses a proof string into an AppIdentity.Proof struct. Returns the parsed proof or raises an exception.
@spec verify_proof( AppIdentity.Proof.t() | String.t(), AppIdentity.App.finder() | AppIdentity.App.input() | AppIdentity.App.t(), [option()] ) :: {:ok, AppIdentity.App.t() | nil} | :error
Verify a AppIdentity
proof value using a a provided app
. Returns {:ok, app}
, {:ok, nil}
, or :error
.
The proof
may be provided either as a string or a parsed
AppIdentity.Proof.t/0
(from parse_proof/1
). String proof values are
usually obtained from HTTP headers. At Kinetic Commerce, this has generally
jeen KCS-Application
or KCS-Service
.
The app
can be provided as one of AppIdentity.App.input/0
,
AppIdentity.App.t/0
, or AppIdentity.App.finder/0
. If provided
a finder, it will be called with the proof
value.
verify_proof/3
has three possible return values:
{:ok, AppIdentity.App}
when the proof is validated against the provided or located application;{:ok, nil}
when the proof matches the provided or located application, but it does not validate.:error
when there is any error during proof validation.
AppIdentity.verify_proof(proof, &IdentityApplications.get!(&1.id))
telemetry
Telemetry
When telemetry is enabled, verif_proof/3
will emit:
[:app_identity, :verify_proof, :start]
[:app_identity, :verify_proof, :stop]
@spec verify_proof!( AppIdentity.Proof.t() | String.t(), AppIdentity.App.finder() | AppIdentity.App.t(), [option()] ) :: AppIdentity.App.t() | nil
Verify a AppIdentity
proof value using a a provided app
. Returns the app,
nil, or raises an exception on error.
The proof
may be provided either as a string or a parsed
AppIdentity.Proof.t/0
(from parse_proof/1
). String proof values are
usually obtained from HTTP headers. At Kinetic Commerce, this has generally
jeen KCS-Application
or KCS-Service
.
The app
can be provided as one of AppIdentity.App.input/0
,
AppIdentity.App.t/0
, or AppIdentity.App.finder/0
. If provided
a finder, it will be called with the proof
value.
verify_proof/3
has two possible return values:
AppIdentity.App
when the proof is validated against the provided or located application;nil
when the proof matches the provided or located application, but it does not validate.
It raises an exception on any error during proof validation.
AppIdentity.verify_proof(proof, &IdentityApplications.get!(&1.id))
telemetry
Telemetry
When telemetry is enabled, verify_proof!/3
will emit:
[:app_identity, :verify_proof, :start]
[:app_identity, :verify_proof, :stop]
Telemetry events are emitted before any error exceptions are thrown.