View Source AppIdentity (AppIdentity for Elixir v1.3.2)
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 struct (AppIdentity.App.t/0).
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
Telemetry may be disabled by setting this for your configuration:
config :app_identity, AppIdentity.Telemetry, enabled: falseRecompile app_identity if this setting is changed.
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.
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() :: binary()
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.
noncecan 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.versioncan 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 |
Functions
@spec generate_proof( AppIdentity.App.t() | AppIdentity.App.loader() | AppIdentity.App.t(), [option()] ) :: {:ok, binary()} | :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
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")
:errorA version 2 app cannot generate a version 1 nonce.
iex> AppIdentity.generate_proof(v2(), version: 1)
:errorA version 2 app will be rejected if the version has been disallowed.
iex> AppIdentity.generate_proof(v2(), disallowed: [1, 2])
:errorTelemetry
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()] ) :: binary()
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
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 proofA version 2 app cannot generate a version 1 nonce.
iex> AppIdentity.generate_proof!(v2(), version: 1)
** (AppIdentity.AppIdentityError) Error generating proofA version 2 app will be rejected if the version has been disallowed.
iex> AppIdentity.generate_proof!(v2(), disallowed: [1, 2])
** (AppIdentity.AppIdentityError) Error generating proofTelemetry
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() | binary()) :: {: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() | binary()) :: 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() | binary(), 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.:errorwhen there is any error during proof validation.
AppIdentity.verify_proof(proof, &IdentityApplications.get!(&1.id))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() | binary(), 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.Appwhen the proof is validated against the provided or located application;nilwhen 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
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.