Class AbstractAuthorizationBuilder<T extends AbstractAuthorizationBuilder<T>>
- Type Parameters:
T- the implementation type
- Direct Known Subclasses:
SnsAuthorizationBuilder,Snws2AuthorizationBuilder
This builder supports an HMAC-SHA256 style digest authentication scheme in the spirit of the AWS S3 Signature v4 scheme, but adapted for SolarNetwork. In this scheme, a generated authorization credential takes the form of an HTTP Authorization header:
SCHEME Credential=C,SignedHeaders=H,Signature=S
The SCHEME is provided by {#link schemeName()}. The
credential C is the identifier provided to the
constructor, and represents a login or token ID. The signed headers
H is a semicolon-delimited list of request header names used when
computing the signature S. The signature S is a
hex-encoded HMAC-SHA256 digest.
The signing key used to sign the HMAC-SHA256 signature S
is a value derived from a provided secret (i.e. password or token secret) by
computing a HMAC-SHA256 digest that uses a specific date (usually the current
date). See computeSigningKey(Instant, String) for more details.
The signing message used in the HMAC-SHA256 signature S
is a value derived from the configurable properties of this class: a date,
verb, path, list of key/value headers, and any other properties defined by
implementing subclasses. This message is provided by the
computeCanonicalRequestMessage(String[]) method. See the
computeSignatureData(Instant, String) method for more details.
- Version:
- 1.0
- Author:
- matt
-
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionAbstractAuthorizationBuilder(String identifier) Construct with a credential. -
Method Summary
Modifier and TypeMethodDescriptionprotected voidAppend the content SHA 256 value to a string buffer.protected voidappendHeaders(String[] headerNames, StringBuilder buf) Append a list of header name and value pairs.build()Compute an Authorization header value from the configured properties on the builder, using a signing key created from a previous call tosaveSigningKey(String)orsigningKey(byte[]).Compute an Authorization header value from the configured properties on the builder, using the provided secret.Compute a signature value from the configured properties on the builder, using a signing key created from a previous call tosaveSigningKey(String)orsigningKey(byte[]).buildSignature(String secret) Compute a signature value from the configured properties on the builder, using the provided secret.Compute the canonical request message.protected abstract StringcomputeCanonicalRequestMessage(String[] headerNames) Compute the canonical request message.computeSignatureData(Instant date, String canonicalRequestMessage) Compute the final signature data.byte[]computeSigningKey(Instant date, String secret) Compute a signing key from a secret key and date.contentSha256(byte[] digest) Set the body content SHA-256 digest value.Set the request date.byte[]Get the content SHA-256 value.getDate()Get the date.Get the headers.getPath()Get the request path.getVerb()Get the verb.Set a header value.Set the headers.headerValue(String headerName) Get the first available header value.headerValues(String headerName) Get all available header values.Set the host.Set the request path.reset()Reset all values to their defaults.saveSigningKey(String secret) Compute and cache the signing key.protected abstract StringGet the authorization scheme name.signingKey(byte[] key) Set the signing key directly.Get the signing key, encoded as hex.protected abstract StringGet the signing key message.String[]Get all configured header names as a sorted array of lower-case values.Set the verb.
-
Field Details
-
AUTHORIZATION_COMPONENT_CREDENTIAL
The authorization header component for the credential (identifier).- See Also:
-
AUTHORIZATION_COMPONENT_HEADERS
The authorization header component for the signed header name list.- See Also:
-
AUTHORIZATION_COMPONENT_SIGNATURE
The authorization header component for the signature.- See Also:
-
-
Constructor Details
-
AbstractAuthorizationBuilder
Construct with a credential.The builder will be initialized and then
reset()will be called so default values are configured.- Parameters:
identifier- the bearer's identifier, such as a token ID or username
-
-
Method Details
-
reset
Reset all values to their defaults.All properties will be set to null except the following:
- verb
- will be set to GET
- path
- Will be set to /
- date
- will be set to the current time
- signingKey
- this value will not be changed
- Returns:
- The builder.
-
date
Set the request date.This will also set the date header with the date's formatted value.
- Parameters:
date- the date to use, or null for the current system time viaInstant.now(); will be truncated to second resolution- Returns:
- this builder
-
getDate
Get the date.- Returns:
- the date
-
verb
Set the verb.The meaning of the verb depends on the communication protocol being used, such as a HTTP method or STOMP command.
- Parameters:
verb- the verb- Returns:
- this builder
- Throws:
IllegalArgumentException- ifverbis null
-
getVerb
Get the verb.- Returns:
- the verb
-
path
Set the request path.- Parameters:
path- the request path to use- Returns:
- this builder
- Throws:
IllegalArgumentException- ifpathis null
-
getPath
Get the request path.- Returns:
- the path
-
host
Set the host.This is a shortcut for calling
#header(String, String)with a host key.- Parameters:
host- the host value- Returns:
- this builder
-
contentSha256
Set the body content SHA-256 digest value.- Parameters:
digest- the digest value to use or null for none; if provided, the array must have a length of 32 and will be copied- Returns:
- this builder
-
getContentSha256
public byte[] getContentSha256()Get the content SHA-256 value.- Returns:
- the content SHA 256
-
appendContentSha256
Append the content SHA 256 value to a string buffer.- Parameters:
buf- the buffer to append to
-
appendHeaders
Append a list of header name and value pairs.- Parameters:
headerNames- the header names to appendbuf- the buffer to append to
-
headers
Set the headers.- Parameters:
headers- the headers to use- Returns:
- this builder
-
getHeaders
Get the headers.- Returns:
- the headers
-
header
Set a header value.Header values are replaced if a given
headerNameis passed more than once.- Parameters:
headerName- the header name to set; this will be stored in lower-caseheaderValue- the header value(s) to set- Returns:
- this builder
- Throws:
IllegalArgumentException- if any argument is null
-
headerValue
Get the first available header value.- Parameters:
headerName- the name of the header to get the first value for- Returns:
- the header value, or null if the header does not exist
-
headerValues
Get all available header values.- Parameters:
headerName- the name of the header to get the values for- Returns:
- the header values, or null if the header does not exist
-
saveSigningKey
Compute and cache the signing key.Signing keys are derived from the a secret value and valid for 7 days, so this method can be used to compute a signing key so that
build()can be called later. The signing date will be set to whatever date is currently configured viadate(Instant), which defaults to the current time for newly created builder instances.- Parameters:
secret- the secret to sign the digest with- Returns:
- this builder
- Throws:
SecurityException- if any error occurs computing the key
-
signingKey
Set the signing key directly.Use this method if a signing key has been computed externally. The effect is the same as in
saveSigningKey(String)in that thebuild()method can then be called to compute the authorization value using this key.- Parameters:
key- the signing key to set- Returns:
- this builder
-
signingKeyHex
Get the signing key, encoded as hex.- Returns:
- the computed or saved signing key encoded as hex, or null if none computed or saved yet
-
signingKeyMessageLiteral
Get the signing key message.- Returns:
- the signing key message
-
computeSigningKey
Compute a signing key from a secret key and date.A signing key is derived from
keyanddateusing the following algorithm:HmacSha256(HmacSha256("SCHEME"+secret, "YYYYMMDD"), "SIGNING_KEY_MESSAGE_LITERAL")The
HmacSha256(key, message)function computes a HMAC+SHA256 digest value. The YYYYMMDD value isdateformatted in the UTC time zone.- Parameters:
date- the signing datesecret- the secret to derive the signing key from- Returns:
- the signing key
- Throws:
IllegalArgumentException- if any argument is null
-
sortedHeaderNames
Get all configured header names as a sorted array of lower-case values.- Returns:
- the sorted array, never null
-
computeCanonicalRequestMessage
Compute the canonical request message.- Returns:
- the message content, never null
- See Also:
-
computeCanonicalRequestMessage
Compute the canonical request message.- Parameters:
headerNames- the header names to include in the signature- Returns:
- the canonical request message
-
computeSignatureData
Compute the final signature data.The message is computed using the following algorithm:
SCHEME_NAME-HMAC-SHA256\n YYYYMMTDDHHmmssZ\n Hex(Sha256(canonicalRequestMessage))The date is formatted using the
AuthorizationUtils.AUTHORIZATION_TIMESTAMP_FORMATTER.- Parameters:
date- the request datecanonicalRequestMessage- the canonical request message, i.e. fromcomputeCanonicalRequestMessage()- Returns:
- the final data to be signed for the request
-
build
Compute an Authorization header value from the configured properties on the builder, using a signing key created from a previous call tosaveSigningKey(String)orsigningKey(byte[]).The message is formatted using the following structure:
SNS Credential=identifier,SignedHeaders=headerList,Signature=Hex(HmacSha256(signingKey,signatureData))Where
identifieris the identifier passed to the constructor,headerListis a semicolon-delimited list ofsortedHeaderNames(),signingKeyis the signing key set viasigningKey(byte[])or computed viasaveSigningKey(String), andsignatureDatais the computed signature data viacomputeSignatureData(Instant, String).- Returns:
- the header value
- Throws:
SecurityException- if any error occurs computing the header value
-
build
Compute an Authorization header value from the configured properties on the builder, using the provided secret.- Parameters:
secret- the secret to sign the digest with; will use the configured date to compute the singing key- Returns:
- the header value
- Throws:
SecurityException- if any error occurs computing the header value- See Also:
-
schemeName
Get the authorization scheme name.- Returns:
- the scheme name
-
buildSignature
Compute a signature value from the configured properties on the builder, using a signing key created from a previous call tosaveSigningKey(String)orsigningKey(byte[]).Note this method returns just the signature value, not a complete Authorization header value. Use the
build()method to generate a complete header value.The signature is computed using the following algorithm:
Hex(HmacSha256(signingKey,signatureData))Where
signingKeyis the signing key set viasigningKey(byte[])or computed viasaveSigningKey(String), andsignatureDatais the computed signature data viacomputeSignatureData(Instant, String).- Returns:
- the signature value
- Throws:
SecurityException- if any error occurs computing the header value
-
buildSignature
Compute a signature value from the configured properties on the builder, using the provided secret.Note this method returns just the signature value, not a complete Authorization header value. Use the
build(String)method to generate a complete header value.- Parameters:
secret- the secret to sign the digest with; will use the configured date to compute the singing key- Returns:
- the signature value
- Throws:
SecurityException- if any error occurs computing the header value- See Also:
-