Documentation ¶
Overview ¶
Package csjwt handles JSON web tokens.
See README.md for more info. http://self-issued.info/docs/draft-jones-json-web-token.html
Further reading: https://float-middle.com/json-web-tokens-jwt-vs-sessions/ and http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
https://news.ycombinator.com/item?id=11929267 => For people using JWT as a substitute for stateful sessions, how do you handle renewal (or revocation)?
https://news.ycombinator.com/item?id=14290114 => Things to Use Instead of JSON Web Tokens (inburke.com) TL;DR: Refactor the library and strip out RSA/ECDSA/encoding/decoding into its own sub-packages.
A new discussion: https://news.ycombinator.com/item?id=13865459 JSON Web Tokens should be avoided (paragonie.com)
Headless JWT mode: https://dev.to/neilmadden/7-best-practices-for-json-web-tokens
TODO: Investigate security bugs: http://blogs.adobe.com/security/2017/03/critical-vulnerability-uncovered-in-json-encryption.html Critical Vulnerability Uncovered in JSON Encryption. Executive Summary: If you are using go-jose, node-jose, jose2go, Nimbus JOSE+JWT or jose4 with ECDH-ES please update to the latest version. RFC 7516 aka JSON Web Encryption (JWE) Invalid Curve Attack. This can allow an attacker to recover the secret key of a party using JWE with Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES), where the sender could extract receiver’s private key.
https://news.ycombinator.com/item?id=14727252 => https://github.com/shieldfy/API-Security-Checklist
https://dadario.com.br/revoking-json-web-tokens/
TODO(CyS) move RSA and ECDSA into its own subpackage ...
TODO(CyS) Consider PAST (Platform-Agnostic Security Tokens) https://news.ycombinator.com/item?id=16070394 https://github.com/paragonie/past
Index ¶
- Constants
- Variables
- func DecodeSegment(seg []byte) ([]byte, error)
- func EncodeSegment(seg []byte) []byte
- func MergeClaims(dst Claimer, srcs ...Claimer) error
- func NewGobEncoding(primeObjects ...interface{}) *gobEncoding
- func Parse(dst *Token, rawToken []byte, keyFunc Keyfunc) error
- func ParseFromRequest(dst *Token, keyFunc Keyfunc, req *http.Request) error
- func SplitForVerify(rawToken []byte) (signingString, signature []byte, err error)
- type Claimer
- type Deserializer
- type Head
- type Header
- type JSONEncoding
- type Key
- func WithECPrivateKey(privateKey *ecdsa.PrivateKey) (k Key)
- func WithECPrivateKeyFromFile(pathToFile string, password ...[]byte) (k Key)
- func WithECPrivateKeyFromPEM(privateKey []byte, password ...[]byte) (k Key)
- func WithECPublicKey(publicKey *ecdsa.PublicKey) (k Key)
- func WithECPublicKeyFromFile(pathToFile string) (k Key)
- func WithECPublicKeyFromPEM(publicKey []byte) (k Key)
- func WithPassword(password []byte) Key
- func WithPasswordFromFile(pathToFile string) Key
- func WithPasswordRandom() Key
- func WithRSAGenerated() (k Key)
- func WithRSAPrivateKey(privateKey *rsa.PrivateKey) (k Key)
- func WithRSAPrivateKeyFromFile(pathToFile string, password ...[]byte) (k Key)
- func WithRSAPrivateKeyFromPEM(privateKey []byte, password ...[]byte) (k Key)
- func WithRSAPublicKey(publicKey *rsa.PublicKey) (k Key)
- func WithRSAPublicKeyFromFile(pathToFile string) (k Key)
- func WithRSAPublicKeyFromPEM(publicKey []byte) (k Key)
- type Keyfunc
- type Serializer
- type Signer
- func MustSigningMethodFactory(alg string) Signer
- func NewSigningMethodBlake2b256(key Key) (Signer, error)
- func NewSigningMethodBlake2b512(key Key) (Signer, error)
- func NewSigningMethodHS256Fast(key Key) (Signer, error)
- func NewSigningMethodHS384Fast(key Key) (Signer, error)
- func NewSigningMethodHS512Fast(key Key) (Signer, error)
- func SigningMethodFactory(alg string) (s Signer, err error)
- type SignerSlice
- type SigningMethodECDSA
- type SigningMethodHMAC
- type SigningMethodHSFast
- type SigningMethodRSA
- type SigningMethodRSAPSS
- type Token
- type Verification
Constants ¶
const ( ES256 = `ES256` ES384 = `ES384` ES512 = `ES512` HS256 = `HS256` HS384 = `HS384` HS512 = `HS512` PS256 = `PS256` PS384 = `PS384` PS512 = `PS512` RS256 = `RS256` RS384 = `RS384` RS512 = `RS512` ES = `ES` HS = `HS` PS = `PS` RS = `RS` Blake2b256 = `blk2b256` Blake2b512 = `blk2b512` )
All available algorithms which are supported by this package.
const ContentTypeJWT = `JWT`
ContentTypeJWT defines the content type of a token. At the moment only JWT is supported. JWE may be added in the future JSON Web Encryption (JWE). https://tools.ietf.org/html/rfc7519
const HTTPFormInputName = `access_token`
HTTPFormInputName default name for the HTML form field name
const HTTPHeaderAuthorization = `Authorization`
HTTPHeaderAuthorization identifies the bearer token in this header key
const PrivateKeyBits = 2048
PrivateKeyBits used when auto generating a private key
Variables ¶
var TimeFunc = time.Now
TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). You can override it to use another time value. This is useful for testing or if your server uses a different time zone than your tokens.
Functions ¶
func DecodeSegment ¶
DecodeSegment decodes JWT specific base64url encoding with padding stripped. Returns a new byte slice. Error behaviour: NotValid.
func EncodeSegment ¶
EncodeSegment encodes JWT specific base64url encoding with padding stripped. Returns a new byte slice.
func MergeClaims ¶
MergeClaims merges the sources Claimers into the destination claimer existing token claims and overwrites existing entries. Destination Claimer must be a pointer. Error behaviour: NotSupported
func NewGobEncoding ¶
func NewGobEncoding(primeObjects ...interface{}) *gobEncoding
NewGobEncoding creates a new primed gob Encoder/Decoder. Newly created Encoder/Decoder will Encode/Decode the passed sample structs without actually writing/reading from their respective Writer/Readers. This is useful for gob which encodes/decodes extra type information whenever it sees a new type. Pass sample values for primeObjects you plan on Encoding/Decoding to this method in order to avoid the storage overhead of encoding their type information for every NewEncoder/NewDecoder. Make sure you use gob.Register() for every type you plan to use otherwise there will be errors. Setting the primeObjects causes a priming of the encoder and decoder for each type. This function panics if the types, used for priming, can neither be encoded nor decoded.
func Parse ¶
Parse parses a rawToken into the destination token and may return an error. You must make sure to set the correct expected headers and claims in the destination Token. The Header and Claims field in the template token must be a pointer, as the destination Token itself.
Default configuration with defined CookieName of constant HTTPFormInputName, defined FormInputNam with value of constant HTTPFormInputName and supported Signers of HS256, HS384 and HS512.
func ParseFromRequest ¶
ParseFromRequest same as Parse but extracts the token from a request. First it searches for the token bearer in the header HTTPHeaderAuthorization. If not found, the cookie gets parsed and if not found then the request POST form gets parsed.
Default configuration with defined CookieName of constant HTTPFormInputName, defined FormInputNam with value of constant HTTPFormInputName and supported Signers of HS256, HS384 and HS512.
func SplitForVerify ¶
SplitForVerify splits the token into two parts: the payload and the signature. An error gets returned if the number of dots don't match with the JWT standard.
Types ¶
type Claimer ¶
type Claimer interface { // Valid method that determines if the token is invalid for any supported reason. // Returns nil on success. Error behaviour: NotValid Valid() error // Expires declares when a token expires. A duration smaller or equal // to zero means that the token has already expired. // Useful when adding a token to a blacklist. Expires() time.Duration // Set sets a value to the claim and may overwrite existing values Set(key string, value interface{}) error // Get retrieves a value from the claim. Get(key string) (value interface{}, err error) // Keys returns a list of all available keys Keys() []string }
Claimer for a type to be a Claims object
type Deserializer ¶
Deserializer provides an interface for providing custom deserializers. Also known as unserialize ;-)
type Head ¶
type Head struct { // Alg (algorithm) header parameter identifies the cryptographic algorithm // used to secure the JWT. A list of reserved alg values is in Table 4. The // processing of the "alg" (algorithm) header parameter, if present, // requires that the value of the "alg" header parameter MUST be one that is // both supported and for which there exists a key for use with that // algorithm associated with the issuer of the JWT. This header parameter is // REQUIRED. Algorithm string `json:"alg,omitempty"` // Typ (type) header parameter is used to declare that this data structure // is a JWT. If a "typ" parameter is present, it is RECOMMENDED that its // value be "JWT". This header parameter is OPTIONAL. Type string `json:"typ,omitempty"` }
Head minimum default header. To extend this header please use the struct jwtclaim.HeadSegments
func NewHead ¶
NewHead creates a new minimum default header. Arguments alg can be optionally applied one time to define an algorithm but in all cases the algorithm gets set by the signing method. For test cases you can pass an algorithm argument. To extend this header please use the struct jwtclaim.HeadSegments
func (*Head) Get ¶
Get returns a value or nil or an error. Key must be one of the constants Header*. Error behaviour: NotSupported
func (*Head) Set ¶
Set sets a value. Key must be one of the constants Header*. Error behaviour: NotSupported
type Header ¶
type Header interface { // Alg returns the name of the underlying algorithm Alg() string // Typ identifies the type of the JSON web token Typ() string // Set error behaviour must be NotSupported Set(key, value string) error // Get error behaviour must be NotSupported Get(key string) (value string, err error) }
Header defines the contract for a type to act like a header. It must be able to marshal and unmarshal itself. The members of the JSON object represented by the Decoded JWT Header Segment describe the signature applied to the JWT Header Segment and the JWT Payload Segment and optionally additional properties of the JWT. Implementations MUST understand the entire contents of the header; otherwise, the JWT MUST be rejected for processing.
type JSONEncoding ¶
type JSONEncoding struct{}
JSONEncoding default JSON de- & serializer with base64 support
func (JSONEncoding) Deserialize ¶
func (jp JSONEncoding) Deserialize(src []byte, dst interface{}) error
Deserialize decodes a value using encoding/json.
func (JSONEncoding) Serialize ¶
func (jp JSONEncoding) Serialize(src interface{}) ([]byte, error)
Serialize encodes a value using encoding/json.
type Key ¶
type Key struct { Error error // contains filtered or unexported fields }
Key defines a container for the HMAC password, RSA and ECDSA public and private keys. The Error fields gets filled out when loading/parsing the keys.
func WithECPrivateKey ¶
func WithECPrivateKey(privateKey *ecdsa.PrivateKey) (k Key)
WithECPrivateKey sets the ECDSA private key. Public key will be derived from the private key.
func WithECPrivateKeyFromFile ¶
WithECPrivateKeyFromFile parses file PEM encoded Elliptic Curve Private Key Structure. Public key will be derived from the private key. Provide a password as a second argument when the private key is encrypted. Public key will be derived from the private key.
func WithECPrivateKeyFromPEM ¶
WithECPrivateKeyFromPEM parses PEM encoded Elliptic Curve Private Key Structure. Provide a password as a second argument when the private key is encrypted. Public key will be derived from the private key.
func WithECPublicKey ¶
WithECPublicKey sets the ECDSA public key
func WithECPublicKeyFromFile ¶
WithECPublicKeyFromFile parses a file PEM encoded Elliptic Curve Public Key Structure.
func WithECPublicKeyFromPEM ¶
WithECPublicKeyFromPEM parses PEM encoded Elliptic Curve Public Key Structure
func WithPassword ¶
WithPassword uses the byte slice as the password for the HMAC-SHA signing method.
func WithPasswordFromFile ¶
WithPasswordFromFile loads the content of a file and uses that content as the password for the HMAC-SHA signing method.
func WithPasswordRandom ¶
func WithPasswordRandom() Key
WithPasswordRandom creates cryptographically secure random password which you cannot obtain. Whenever you restart your app with a random password, all HMAC-SHA tokens get invalided.
func WithRSAGenerated ¶
func WithRSAGenerated() (k Key)
WithRSAGenerated creates an in-memory private key to be used for signing and verifying. Bit size see constant: PrivateKeyBits Public key will be derived from the private key.
func WithRSAPrivateKey ¶
func WithRSAPrivateKey(privateKey *rsa.PrivateKey) (k Key)
WithRSAPrivateKey sets the private key. Public key will be derived from the private key.
func WithRSAPrivateKeyFromFile ¶
WithRSAPrivateKeyFromFile parses PEM encoded PKCS1 or PKCS8 private key found in a file. Provide a password as a second argument when the private key is encrypted. Public key will be derived from the private key.
func WithRSAPrivateKeyFromPEM ¶
WithRSAPrivateKeyFromPEM parses PEM encoded PKCS1 or PKCS8 private key. Provide a password as a second argument when the private key is encrypted. Public key will be derived from the private key.
func WithRSAPublicKey ¶
WithRSAPublicKey sets the public key
func WithRSAPublicKeyFromFile ¶
WithRSAPublicKeyFromFile parses PEM encoded PKCS1 or PKCS8 public key found in a file.
func WithRSAPublicKeyFromPEM ¶
WithRSAPublicKeyFromPEM parses PEM encoded PKCS1 or PKCS8 public key
func (Key) Algorithm ¶
Algorithm returns the supported algorithm but not the bit size. Returns 0 on error, or one of the constants: ES, HS or RS.
type Keyfunc ¶
Keyfunc used by Parse methods, this callback function supplies the key for verification. The function receives the parsed, but unverified Token. This allows you to use properties in the Header of the token (such as `kid`) to identify which key to use.
func NewKeyFunc ¶
NewKeyFunc creates a new function for token validation and specific key returning. This function checks only if the token algorithm matches the algorithm of the Signer. csjwt.NewVerification() allows you to add also Signers as arguments to check for the correct signatures, but this function is more specific and returns the correct key to check the signature.
type Serializer ¶
Serializer provides an interface for providing custom serializers.
type Signer ¶
type Signer interface { // Verify returns nil if signature is valid Verify(signingString, signature []byte, key Key) error // Sign returns encoded signature or error Sign(signingString []byte, key Key) ([]byte, error) // Alg returns the alg identifier for this method (example: 'HS256') Alg() string }
Signer interface to add new methods for signing or verifying tokens.
func MustSigningMethodFactory ¶
MustSigningMethodFactory same as SigningMethodFactory but panics on error. You should only use the Must* functions during init process or testing.
func NewSigningMethodBlake2b256 ¶
NewSigningMethodBlake2b256 creates a new HMAC-Blake2b hash with a preset password and 32-byte checksum. Blake2b uses SIMD optimizations via ASM code. https://blake2.net/
func NewSigningMethodBlake2b512 ¶
NewSigningMethodBlake2b512 creates a new HMAC-Blake2b hash with a preset password and 64-byte checksum. Blake2b uses SIMD optimizations via ASM code. https://blake2.net/
func NewSigningMethodHS256Fast ¶
NewSigningMethodHS256Fast creates a new HMAC-SHA hash with a preset password and does not register it globally. It uses internally a sync.Pool hashes.
func NewSigningMethodHS384Fast ¶
NewSigningMethodHS384Fast creates a new HMAC-SHA hash with a preset password and does not register it globally. It uses internally a sync.Pool hashes.
func NewSigningMethodHS512Fast ¶
NewSigningMethodHS512Fast creates a new HMAC-SHA hash with a preset password and does not register it globally. It uses internally a sync.Pool hashes.
func SigningMethodFactory ¶
SigningMethodFactory creates a new signing method by an algorithm. Supported algorithms are: ES, HS, PS and RS, all within 256-512 and they do not need a symmetric key. Returns an error for an unknown signing method.
type SignerSlice ¶
type SignerSlice []Signer
SignerSlice helper type
func (SignerSlice) Contains ¶
func (ms SignerSlice) Contains(alg string) bool
Contains checks if the algorithm has already been added
func (SignerSlice) String ¶
func (ms SignerSlice) String() string
String returns a list of algorithms, comma separated
type SigningMethodECDSA ¶
SigningMethodECDSA implements the ECDSA family of signing methods signing methods.
func NewSigningMethodES256 ¶
func NewSigningMethodES256() *SigningMethodECDSA
NewSigningMethodES256 creates a new 256bit ECDSA SHA instance and registers it.
func NewSigningMethodES384 ¶
func NewSigningMethodES384() *SigningMethodECDSA
NewSigningMethodES384 creates a new 384bit ECDSA SHA instance and registers it.
func NewSigningMethodES512 ¶
func NewSigningMethodES512() *SigningMethodECDSA
NewSigningMethodES512 creates a new 512bit ECDSA SHA instance and registers it.
func (*SigningMethodECDSA) Alg ¶
func (m *SigningMethodECDSA) Alg() string
Alg returns the name of the underlying algorithm.
func (*SigningMethodECDSA) Sign ¶
func (m *SigningMethodECDSA) Sign(signingString []byte, key Key) ([]byte, error)
Sign implements the Sign method from SigningMethod. For the key you can use any of the WithECPrivateKey*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid.
func (*SigningMethodECDSA) Verify ¶
func (m *SigningMethodECDSA) Verify(signingString, signature []byte, key Key) error
Verify implements the Verify method from SigningMethod interface. For the key you can use any of the WithEC*Key*() functions Error behaviour: Empty, NotImplemented, WriteFailed, NotValid.
type SigningMethodHMAC ¶
SigningMethodHMAC implements the HMAC-SHA family of signing methods signing methods.
func NewSigningMethodHS256 ¶
func NewSigningMethodHS256() *SigningMethodHMAC
NewSigningMethodHS256 creates a new 256bit HMAC SHA instance and registers it.
func NewSigningMethodHS384 ¶
func NewSigningMethodHS384() *SigningMethodHMAC
NewSigningMethodHS384 creates a new 384bit HMAC SHA instance and registers it.
func NewSigningMethodHS512 ¶
func NewSigningMethodHS512() *SigningMethodHMAC
NewSigningMethodHS512 creates a new 512bit HMAC SHA instance and registers it.
func (*SigningMethodHMAC) Alg ¶
func (m *SigningMethodHMAC) Alg() string
Alg returns the used algorithm.
func (*SigningMethodHMAC) Sign ¶
func (m *SigningMethodHMAC) Sign(signingString []byte, key Key) ([]byte, error)
Sign implements the Sign method from SigningMethod interface. For the key you can use any of the WithPassword*() functions. Error behaviour: Empty, NotImplemented, WriteFailed
func (*SigningMethodHMAC) Verify ¶
func (m *SigningMethodHMAC) Verify(signingString, signature []byte, key Key) error
Verify the signature of HSXXX tokens. Returns nil if the signature is valid. For the key you can use any of the WithPassword*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid.
type SigningMethodHSFast ¶
type SigningMethodHSFast struct { Name string // contains filtered or unexported fields }
SigningMethodHSFast implements the HMAC-SHA family of pre-warmed signing methods. Less allocations, bytes and a little bit faster but maybe the underlying mutex can become the bottleneck.
func (*SigningMethodHSFast) Alg ¶
func (m *SigningMethodHSFast) Alg() string
type SigningMethodRSA ¶
SigningMethodRSA implements the RSA family of signing methods signing methods
func NewSigningMethodRS256 ¶
func NewSigningMethodRS256() *SigningMethodRSA
NewSigningMethodRS256 creates a new 256bit RSA SHA instance and registers it.
func NewSigningMethodRS384 ¶
func NewSigningMethodRS384() *SigningMethodRSA
NewSigningMethodRS384 creates a new 384bit RSA SHA instance and registers it.
func NewSigningMethodRS512 ¶
func NewSigningMethodRS512() *SigningMethodRSA
NewSigningMethodRS512 creates a new 512bit RSA SHA instance and registers it.
func (*SigningMethodRSA) Alg ¶
func (m *SigningMethodRSA) Alg() string
func (*SigningMethodRSA) Sign ¶
func (m *SigningMethodRSA) Sign(signingString []byte, key Key) ([]byte, error)
Sign implements the Sign method from SigningMethod interface. For the key you can use any of the WithRSAPrivateKey*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid.
func (*SigningMethodRSA) Verify ¶
func (m *SigningMethodRSA) Verify(signingString, signature []byte, key Key) error
Verify implements the Verify method from SigningMethod interface. For the key you can use any of the WithRSA*Key*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid
type SigningMethodRSAPSS ¶
type SigningMethodRSAPSS struct { SigningMethodRSA Options rsa.PSSOptions }
SigningMethodRSAPSS implements the RSAPSS family of signing methods signing methods.
func NewSigningMethodPS256 ¶
func NewSigningMethodPS256() *SigningMethodRSAPSS
NewSigningMethodPS256 creates a new 256bit RSAPSS SHA instance and registers it.
func NewSigningMethodPS384 ¶
func NewSigningMethodPS384() *SigningMethodRSAPSS
NewSigningMethodPS384 creates a new 384bit RSAPSS SHA instance and registers it.
func NewSigningMethodPS512 ¶
func NewSigningMethodPS512() *SigningMethodRSAPSS
NewSigningMethodPS512 creates a new 512bit RSAPSS SHA instance and registers it.
func (*SigningMethodRSAPSS) Sign ¶
func (m *SigningMethodRSAPSS) Sign(signingString []byte, key Key) ([]byte, error)
Sign implements the Sign method from SigningMethod interface. For the key you can use any of the WithRSAPrivateKey*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid.
func (*SigningMethodRSAPSS) Verify ¶
func (m *SigningMethodRSAPSS) Verify(signingString, signature []byte, key Key) error
Verify implements the Verify method from SigningMethod interface. For the key you can use any of the WithRSA*Key*() functions. Error behaviour: Empty, NotImplemented, WriteFailed, NotValid
type Token ¶
type Token struct { Raw []byte // The raw token. Populated when you Parse a token Header Header // The first segment of the token Claims Claimer // The second segment of the token Signature []byte // The third segment of the token. Populated when you Parse a token Valid bool // Is the token valid? Populated when you Parse/Verify a token Serializer }
Token represents a JWT Token. Different fields will be used depending on whether you're creating or parsing/verifying a token.
func NewToken ¶
NewToken creates a new Token and presets the header to typ = JWT. A new token has not yet an assigned algorithm. The underlying default template header consists of a two field struct for the minimum requirements. If you need more header fields consider using a map or the jwtclaim.HeadSegments type. Default header from function NewHead().
func (Token) MarshalLog ¶
MarshalLog marshals the token into an unsigned log.Field. It uses the function SigningString().
func (Token) SignedString ¶
SignedString gets the complete, signed token. Sets the header alg to the provided Signer.Alg() value. Returns a byte slice, save for further processing. This functions allows to sign a token with different signing methods.
func (Token) SigningString ¶
SigningString generates the signing string. This is the most expensive part of the whole deal. Unless you need this for something special, just go straight for the SignedString. Returns a buffer which can be used for further modifications.
type Verification ¶
type Verification struct { // FormInputName defines the name of the HTML form input type in which the // token has been stored. If empty, the form the gets ignored. FormInputName string // CookieName defines the name of the cookie where the token has been stored. If // empty, cookie parsing gets ignored. CookieName string // Methods for verifying and signing a token Methods SignerSlice // Decoder interface to pass in a custom decoder parser. Can be nil, falls // back to JSON. Deserializer }
Verification allows to parse and verify a token with custom options.
func NewVerification ¶
func NewVerification(availableSigners ...Signer) *Verification
NewVerification creates new verification parser with the default signing method HS256, if availableSigners slice argument is empty. Nil arguments are forbidden.
func (*Verification) Parse ¶
func (vf *Verification) Parse(dst *Token, rawToken []byte, keyFunc Keyfunc) error
Parse parses a rawToken into the destination token and may return an error. You must make sure to set the correct expected headers and claims in the template Token. The Header and Claims field in the destination token must be a pointer as the token itself. Error behaviour: Empty, NotFound, NotValid
func (*Verification) ParseFromRequest ¶
ParseFromRequest same as Parse but extracts the token from a request. First it searches for the token bearer in the header HTTPHeaderAuthorization. If not found the request POST form gets parsed and the FormInputName gets used to lookup the token value.