Tokens are the primary mechanism to implement single sign on for all the user apps.
A token is used by the client to create a secure channel with its corresponding CA running in the cloud.
We use the JSON Web Tokens (draft-ietf-oauth-json-web-token-32) format for our tokens.
Not all apps are equally trusted, and we want to ensure that a rogue app cannot reuse tokens in a different context.
We achieve that by weakening tokens with the following optional constraints:
-
appPublisher
: publisher of the app hosting CAs. -
appLocalName
: name of the app in theappPublisher
context. -
caOwner
: owner name of the CA. -
caLocalName
: name of the CA in the owner's context. -
expiresAfter
: Expire time of token in milliseconds since midnight January 1,1970 UTC
Tokens form a meet semi-lattice, where a meet (^
) operator defines a
partial ordering of tokens, i.e.,:
A^B = A iff A <= B
and this makes it much simpler to weaken tokens.
In fact, in CAF if you have a valid token you can always request a weaker one regardless of who you are. Providing a service to manage user tokens becomes trivial.
The meet (^) operator is just simply set intersection for each of the constraints:
a^a = a
a^* = a
*^b = b
a^b = 'empty' when (a !== b and a !== * and b !== *)
and in the case of expiresAfter
, pick the shortest deadline.
ACLs (Access Control Lists) are also expressed with the same semi-lattice, using the meet operator for access checks:
ALLOW if ACL[i] ^ Token != empty for some ACL[i] in ACL
where the result of ^ is 'empty' if any of the constraints has an 'empty' set.
Methods
decode(tokenStr) → {tokenType}
Decode a token without doing any checks. This is sometimes useful to choose a public key for validation.
Parameters:
Name | Type | Description |
---|---|---|
tokenStr |
string | A string encoding a token. |
Returns:
An untrusted token that has NOT been validated.
- Type
- tokenType
lessOrEqual(t1, t2) → {boolean}
Whether for tokens t1 and t2, t1 <= t2.
Note that null
represents the empty token, and null <= t2 for all t2
.
Parameters:
Name | Type | Description |
---|---|---|
t1 |
tokenType | A token to compare. |
t2 |
tokenType | A token to compare. |
Throws:
-
Malformed token.
- Type
- Error
Returns:
t1 <= t2
- Type
- boolean
meet(t1, t2) → {tokenType|null}
'Meet' (^) operation of two tokens. Performs set intersection for each
constraint, and if any resulting constraint is empty it returns null
, the
empty token.
A missing constraint is assumed to be *
, i.e., all the elements in the
set.
Intersection of expiresAfter
uses time intervals.
There is no validation of the tokens or signing of the result.
Parameters:
Name | Type | Description |
---|---|---|
t1 |
tokenType | A token to combine with the 'meet' operator. |
t2 |
tokenType | A token to combine with the 'meet' operator. |
Returns:
Null if the resulting set is empty or an unsigned token payload with 't1^t2'.
- Type
- tokenType | null
newPayload(appPublisheropt, appLocalNameopt, caOwneropt, caLocalNameopt, durationInSecopt) → {tokenType}
Constructor for a new token or acl element payload.
The type of tokenType is
{appPublisher: string=, appLocalName:string=,
caOwner: string=, caLocalName: string=, expiresAfter: number=}
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
appPublisher |
string |
<optional> |
Publisher of the app hosting CAs. |
appLocalName |
string |
<optional> |
Name of the app in the 'appPublisher' context. |
caOwner |
string |
<optional> |
Owner of the CA. |
caLocalName |
string |
<optional> |
Name of the CA in the owner's context. |
durationInSec |
number |
<optional> |
Time in seconds from 'now' till token expires. |
Throws:
-
when input is malformed.
- Type
- Error
Returns:
A token or acl element payload.
- Type
- tokenType
satisfyACL(acl, token) → {boolean}
Checks whether a valid token satisfies an ACL (Access control List).
Inefficient with many ACLs. See module:caf_security/rules for a recommended alternative.
Parameters:
Name | Type | Description |
---|---|---|
acl |
Array.<tokenType> | tokenType | An ACL formed with one or an array of constraints using a token format. |
token |
tokenType | A previously validated token to check 'acl'. |
Returns:
True if satisfies at least one element of the ACL.
- Type
- boolean
sign(token, privKey) → {string}
Signs a token.
Parameters:
Name | Type | Description |
---|---|---|
token |
tokenType | Token to sign. |
privKey |
Object | Private key for signing. |
Throws:
-
Cannot sign.
- Type
- Error
Returns:
A serialized signed token.
- Type
- string
similar(t1, t2, ignoreExpires) → {boolean}
Deep equality of two tokens ignoring fields that are not constraints.
Note that null
represents the empty token.
Parameters:
Name | Type | Description |
---|---|---|
t1 |
tokenType | A token to compare. |
t2 |
tokenType | A token to compare. |
ignoreExpires |
boolean | True if we ignore the token expire date. |
Returns:
t1 similarTo t2
- Type
- boolean
validate(tokenStr, pubKey)
Validates a token.
Checks signature, expire time, and string format (ASCII alphanumeric).
Parameters:
Name | Type | Description |
---|---|---|
tokenStr |
string | A string with the encoded token. |
pubKey |
Object | A public key to validate the token |
Throws:
-
Token does not validate
- Type
- Error
validExtendedNobody(from) → {boolean}
Checks whether a username is an extended NOBODY user.
This user can have many CAs as long as their names have only two characters.
Parameters:
Name | Type | Description |
---|---|---|
from |
string | A full name, e.g., |
Returns:
True if ok, false otherwise.
- Type
- boolean
validUsername(username) → {boolean}
Checks whether a username contains only valid characters (lower case letters and numbers, ASCII only), and it has at least three characters.
Parameters:
Name | Type | Description |
---|---|---|
username |
string | A username to check. |
Returns:
True if ok, false otherwise.
- Type
- boolean