Ephemeral Tokens
About Ephemeral Tokens
Ephemeral tokens are tokens issued by KAZOO with a payload of the creator’s choosing that can later be verified by another service and the payload retrieved. Use these tokens to create service integrations where KAZOO is used to validate and decrypt a provided token and the resulting payload is used by the service.
Schema
ephemeral token payloads
Key | Description | Type | Default | Required | Support Level |
---|---|---|---|---|---|
claims | Provided claims from the client to encode in the token | object() | true |
Create an ephemeral token
Within the claims
object, put whatever data you’d like encoded in the encrypted payload.
PUT /v2/accounts/{ACCOUNT_ID}/ephemeral_tokens
curl -v -X PUT \
-H "X-Auth-Token: {API_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/ephemeral_tokens \
-d '{"data":{"claims":{"secret":"data"}}}'
{"data":{"token":"{SHINY_JWT_TOKEN}"
,"id":"{TOKEN_ID}"
}
,"timestamp":"{TIMESTAMP}"
,"version":"{VERSION}"
,"node":"{NODE}"
,"request_id":"{REQUEST_ID}"
,"status":"success"
,"tokens":{"consumed":1,"remaining":100}
,"auth_token":"{API_TOKEN}"
}
Fetch the claims of an ephemeral token
GET /v2/accounts/{ACCOUNT_ID}/ephemeral_tokens/{SHINY_JWT_TOKEN}
Returns the data encoded in the token along with some metadata.
The base payload returns will contain:
{"data":{
"account_id":"{ACCOUNT_ID}"
,"exp":{UNIX_TIMESTAMP}
,"identity_sig":"{SIGNATURE}"
,"iss":"kazoo"
,"method":"cb_ephemeral_tokens"
"id": "{TOKEN_ID}"
...
}
}
There will also be SIP information:
"SIP-Info":{
"User-Agent":{
"Realm":"{ACCOUNT_REALM}"
,"Username":"{SIP_USERNAME}"
}
}
The rest of the returned data object will be the data encoded in the creation of the token.
curl -v -X GET \
-H "X-Auth-Token: {API_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/ephemeral_tokens/{SHINY_NEW_TOKEN}
{"data":{
"account_id":"{ACCOUNT_ID}"
,"exp":{UNIX_TIMESTAMP}
,"identity_sig":"{SIGNATURE}"
,"iss":"kazoo"
,"method":"cb_ephemeral_tokens"
,"id":"{TOKEN_ID}"
,"secret":"data"
,"scope":"sip"
,"sub":"{SUB}"
}
,"timestamp":"{TIMESTAMP}"
,"version":"{VERSION}"
,"node":"{NODE}"
,"request_id":"{REQUEST_ID}"
,"status":"success"
,"tokens":{"consumed":1,"remaining":100}
,"auth_token":"{API_TOKEN}"
}
SIP calls with Ephemeral tokens
Now that you have your shiny new token, you can register a SIP device over a WebRTC connection.
Use the token’s ID as your SIP username, the account’s SIP realm, and set the Authorization
header to the token. The issued REGISTER packet should look something like this:
REGISTER sip:kamailio.server.com SIP/2.0
Via: SIP/2.0/UDP client.com:42400;branch=f320f2ba9fae
To: <sip:{TOKEN_ID}@{ACCOUNT_REALM}>
From: <sip:2db66f904c12a632111330640c07552f@{ACCOUNT_REALM}>;tag=60987672
Call-Id: {CALL_ID}
CSeq: 1 REGISTER
Max-Forwards: 70
Authorization: {SHINY_NEW_TOKEN}
Contact: <sip:{TOKEN_ID}@{ACCOUNT_REALM}>
Expires: 2600
User-Agent: libwebphone
Content-Length: 0
Note
This requires the jwt
role to be installed and enabled on the Kamailio servers. Kamailio also must be >= 5.3.5
Callflows
To route calls to the ephemeral device, you need a callflow created with the ephemeral_device
callflow action:
"flow":{
"module":"ephemeral_device"
,"data":{
"token_id":"{TOKEN_ID}"
,"dial_strategy":"simultaneous"
,"timeout":20
}
}
Of course this could be served via Pivot callflow response or a channels
API action. The settings of the callflow action mostly mirror the device
action.
Device-based tokens
First and foremost, this method of authentication should only be used over secure connections (like WebRTC or SIPS) as the Authorization
SIP header will contain that token that, if sniffed, could be used by other user agents (at least until it expires).
To generate tokens for authentication, the device needs to have the sip.method
path set to authorization
:
{
"sip": {
"method": "authorization"
}
}
Generate an Authorization
token for a device
curl -v -X PUT \
-H "X-Auth-Token: {API_TOKEN}" \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/devices/{DEVICE_ID}/ephemeral_tokens \
-d '{"data":{"claims":{"secret":"data"}}}'
{
"auth_token": "{API_TOKEN}",
"data": {
"id": "{TOKEN_ID}",
"token": "{AUTHZ_TOKEN}"
},
"node": "{NODE}",
"request_id": "{REQUEST_ID}",
"status": "success",
"timestamp": "{TIMESTAMP}",
"tokens": {
"consumed": 1,
"remaining": 100
},
"version": "{VSN}"
}
Decode your token
curl -v -X GET \
-H "X-Auth-Token: {API_TOKEN} \
http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/ephemeral_tokens/{AUTHZ_TOKEN}
{
"auth_token": "{API_TOKEN}",
"data": {
"secret": "data",
"SIP-Info": {
"Authorizing-ID": "{DEVICE_ID}",
"User-Agent": {
"Realm": "0060a2.sip.2600hz.com",
"Username": "{TOKEN_ID}"
}
},
"account_id": "{ACCOUNT_ID}",
"exp": 1607923214,
"id": "{TOKEN_ID}",
"identity_sig": "{SIGNATURE}",
"iss": "kazoo",
"method": "cb_ephemeral_tokens",
"scope": "sip",
"sub": "{TOKEN_ID}@{ACCOUNT_ID}"
},
"node": "{NODE}",
"request_id": "{REQUEST_ID}",
"status": "success",
"timestamp": "{TIMESTAMP}",
"tokens": {
"consumed": 1,
"remaining": 100
},
"version": "{VSN}"
}
REGISTER your device
Using the {AUTHZ_TOKEN}
value in your user agent’s Authorization
header results in a SIP packet like:
REGISTER sip:{SIP_SERVER} SIP/2.0
Via: SIP/2.0/TCP {HOST}:48827;branch=768403aff237
To: <sip:{TOKEN_ID}@{SIP_REALM}>
From: <sip:{TOKEN_ID}@{SIP_REALM}>;tag=3328e732
Call-Id: {CALL_ID}
CSeq: 1 REGISTER
Max-Forwards: 70
Authorization: {AUTHZ_TOKEN}
Contact: <sip:{TOKEN_ID}@{SIP_REALM}>
Expires: 2600
Content-Length: 0
Caveats and notes
At present, Authorization
headers for REGISTER packets will act like regular credentialed registration - one registration per device, with the most recent REGISTER taking precedence for calls to the device.
For outbound, authorization will be performed on the header if no registration is found. Thus any amount of outbound-only user agents can utilize a unique token generated for the device.
Currently token expiration is configured via system configs and defaults to one hour. User agents should be ready to fetch new tokens and re-register accordingly.
Requests
- Routing information in the Req
- Add DELETE to revoke the tokens
Use cases
Token-based user agents
Create a token with no associated device. Each token creates a unique registration to the user agent.
Engineering notes
The token’s “sub” will be {TokenId}@{AccountId}
and SIP-Info.Username={TokenId}
Token-based devices
Create a device with sip.method = "authorization
. Create a token based on that device ID, insert into the user agent’s Authorization
header, and REGISTER (creating a registration for the device based on the token).
When you generate a new token for the device and REGISTER, the new token’s registration will replace the other token’s registration (just as if you re-registered a traditional SIP device).
Engineering notes
The token’s “sub” will be {DeviceId}@{AccountId}
and SIP-Info.Username={TokenId}
Token-based meta devices
Create a “meta-device” device with sip.method = "authorization"
and device_type="meta"
. Each token generated from that device ID can then be used by unique user agents (registrations by different tokens will not overwrite other tokens’ registration). Each user agent will use the settings of the “meta” device’s configuration as expected (caller ID, codec lists, etc) when making calls.
Engineering notes
The token’s “sub” will be {TokenId}@{AccountId}
and SIP-Info:{Username={TokenId}, Endpoint-Meta-ID:{DeviceId}