Bearer Token Generation

A Bearer Token (RFC 6750) is a cryptic string, usually generated by the server in response to a login request. It contains a subject claim (sub) which references an authorized entity (i.e., the User, Application or Organization). The authorized entity uses a signed bearer authorization token to access one or more resources for which the Token was authorized.

The client must send the bearer token in the Authorization header when making requests to protected resources:

Authorization: Bearer GI0OG.ZkNDZlZTIzNGFlNjM1MTV.iMWMw

Please note that you can also pass the the bearer token via the access_token variable in a JSON document or a HTML formfield with the name bearer.

A JavaScript OpeinID Connect Live Demo can be found HERE.

Context
A few years ago, before the JWT (RFC 7519) revolution, a was just a string with no intrinsic meaning, e.g. 2pQS6RQmdApE0TW93X. That token was then looked-up in a database, which held the claims for that token. The downside of this approach is that DB access (or a cache) is required every time the token is used.

JWTs (RFC 7519) encode and verify (via signing) their own claims. This allows folks to issue short-lived JWTs that are stateless (read: self-contained, don’t depend on anybody else). They do not need to hit the DB. This reduces DB load and simplifies application architecture because only the service that issues the JWTs needs to worry about hitting the DB/persistence layer.

The CodeB Middleware offers a simple identity layer on top of its Self-Sovereign Identity system. It enables Clients to verify the identity of the End-User based on the authentication performed by a blockchain node, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

Instead of defining new operations the middleware relies on the use of industry standard for identity information such as OpenID Connect (http://openid.net/specs/openid-connect-core-1_0.html) and OAuth2.0 (RFC6749).

The following is a non-normative example of a Token Request (with line wraps within values for display purposes only):


POST /post.aspx HTTP/1.1
Host: coin.codeb.io
Content-Type: application/x-www-form-urlencoded

grant_type=password
&scope=openid
&username=0x411fd7d291c185485675d8fadd79341f8921f02b
&password=aloaha123
&client_ID=0xd68608d8e960a7e13f2756f508c7371e03ba176f

To try it out you can post the above to: https://coin.codeb.io/post.aspx

In case you need to post the above data in JSON format kindly use the following syntax:

POST /post.aspx HTTP/1.1
Host: coin.codeb.io
Content-Type: application/json

{
“@type”:”specs/bearer”,
“grant_type”:”password”,
“scope”: [“openid”,”createssi”],
“username”:”0x411fd7d291c185485675d8fadd79341f8921f02b“,
“client_id”: “0xd68608d8e960a7e13f2756f508c7371e03ba176f“,
“password”:”aloaha123″,
“max_age”:500
}

The above JSON Syntax is also valid for the Websocket API.

or in GET notation:

https://coin.codeb.io/post.aspx?grant_type=password&scope=openid%20email&username=0x411fd7d291c185485675d8fadd79341f8921f02b&password=aloaha123&client_ID=0xd68608d8e960a7e13f2756f508c7371e03ba176f&max_age=500

The username field contains the principal account created HERE.

To demonstrate how this system can act as an identity provider we connected it to our internal NextCloud on: https://www.aloaha.com:8443 (use “Login is CodeB SSI”) and username: 0x411fd7d291c185485675d8fadd79341f8921f02b with password: aloaha123

Note: Query parameters are never protected by any encryption. POST is always preferred over GET

The following is a non-normative example of a successful Token Response.


HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
“token_type”:”Bearer”,
“expires_in”:35993,
“id_token”:”
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImVjY3B1YiI6IlJVTkxNU0FBQUFBTEhaYnpUUjVTa0F6WWZ6a0dyQnh2OTJiQlA3OGVvcERiSkxtUFdOVUc2NzJmTHlkdk9vR1RUSXZ3MFlsZlI2X0dPUFVIWkhUTnRSc29paUhBR1ZiMSJ9.eyJzdWIiOiIweDQxMWZkN2QyOTFjMTg1NDg1Njc1ZDhmYWRkNzkzNDFmODkyMWYwMmIiLCJVc2VyUHViS2V5IjoiMHgwNDYxMzMyM2E0ZDhjODkzNjhkMGQ3YzU2MmVjNTM3OGNmMTRlZTRjMDQwMTU2MzcxNTQyMDVmNWIxNGZlN2RkYmM2MWRhNGM2ZjI1NjZiNGI4NzFhZmRhNDI2MDcwZDVmN2U1MzdlYmU3NDI5ODRkYzQ4MTZmZjlkMDIzNzljMmE3IiwiYXVkIjoiMHhkNjg2MDhkOGU5NjBhN2UxM2YyNzU2ZjUwOGM3MzcxZTAzYmExNzZmIiwiYXV0aF90aW1lIjoiMTYwNzcwNjgxMyIsImlhdCI6IjE2MDc3MDY4MTIiLCJzY29wZSI6WyJvcGVuaWQiLCJlbWFpbCJdLCJleHAiOiIxNjEzNzE2NzcyIiwibm9uY2UiOiI5ZTE0MDUzNTYzNmQ0YTA4OWQwNTQ0NGUzMzAxOTNiMyIsImNsaWVudF9pZCI6IjB4ZDY4NjA4ZDhlOTYwYTdlMTNmMjc1NmY1MDhjNzM3MWUwM2JhMTc2ZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCJ9.nsXQCdM5Lju5KMEf6PAXmZRHFwOMpu92Uy5JCrpUy5d0B8c9_3B1Pk3XsKJZo7knvEqYnqfpbGIEPtgayaN79Q” }

The decoded content of the id_token is:

Header:

When verifying a JWT, the algorithm used for signing and an identifier referencing the public key to use for signature verification can be found in the header:

{
“alg”: “ES256”,
“typ”: “JWT”,
“eccpub”: “RUNLMSAAAADk-Gf4YF_m5IpqOJIk6vHl4dw0_ry0f6F70_1C_cOi_ihhaiyH6aRP9PwunOe3GtwzReBcI0xdn1IIFNWQpvzf”
}

Payload:

The encoded JWT will, in most cases, include an expiration timestamp (exp) after which the token is no longer valid. A Token issued without an expiration date must be explicitly revoked.
The following payload illustrates how standard and application-specific claims are encoded in a bearer JWT:

{
“sub”: “0x7f2aC5165E1B228720231799236647cEB7FE410D”,
“UserPubKey”: “0x04cd7f6d5105524370e40896a980aa2baae3c2428b52ce5ed4684b48fd46ee234ae63515b1c06ddd37ac411b67dea2a89fa743750296aae44f270f139111fbc054”,
“aud”: “0x7f2aC5165E1B228720231799236647cEB7FE410D”,
“auth_time”: “1607073741”,
“iat”: “1607073739”,
“exp”: “1607109736”,
“nonce”: “d7ff7aed52cf4952b1977997e8250fab”,
“client_id”: “0x7f2aC5165E1B228720231799236647cEB7FE410D”,
“grant_type”: “password”,
“~thread”: {
“thid”: “10c1de0b-64e5-4a18-ad59-56d069ce0c0a”
},
“@id”: “719b311b-7cf8-441f-9ba9-4e88e6ea7ef1”
}

Signature:

The encoded JWT is digitally signed using either the users or nodes private key:

GYeXmtsnfqj32LPtbSSXKV06ZHgMSXdZFh8YbkGKi701SyEhm2U4KU5QMq9Fp4w2_-J83y1pTQw5q15H1qwjQw

With the bearer token you can query the userinfo allowed by the scope in the original request:

https://coin.codeb.io/userinfo.aspx?bearer=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImVjY3B1YiI6IlJVTkxNU0FBQUFBTEhaYnpUUjVTa0F6WWZ6a0dyQnh2OTJiQlA3OGVvcERiSkxtUFdOVUc2NzJmTHlkdk9vR1RUSXZ3MFlsZlI2X0dPUFVIWkhUTnRSc29paUhBR1ZiMSJ9.eyJzdWIiOiIweDQxMWZkN2QyOTFjMTg1NDg1Njc1ZDhmYWRkNzkzNDFmODkyMWYwMmIiLCJVc2VyUHViS2V5IjoiMHgwNDYxMzMyM2E0ZDhjODkzNjhkMGQ3YzU2MmVjNTM3OGNmMTRlZTRjMDQwMTU2MzcxNTQyMDVmNWIxNGZlN2RkYmM2MWRhNGM2ZjI1NjZiNGI4NzFhZmRhNDI2MDcwZDVmN2U1MzdlYmU3NDI5ODRkYzQ4MTZmZjlkMDIzNzljMmE3IiwiYXVkIjoiMHhkNjg2MDhkOGU5NjBhN2UxM2YyNzU2ZjUwOGM3MzcxZTAzYmExNzZmIiwiYXV0aF90aW1lIjoiMTYwNzcwNjgxMyIsImlhdCI6IjE2MDc3MDY4MTIiLCJzY29wZSI6WyJvcGVuaWQiLCJlbWFpbCJdLCJleHAiOiIxNjEzNzE2NzcyIiwibm9uY2UiOiI5ZTE0MDUzNTYzNmQ0YTA4OWQwNTQ0NGUzMzAxOTNiMyIsImNsaWVudF9pZCI6IjB4ZDY4NjA4ZDhlOTYwYTdlMTNmMjc1NmY1MDhjNzM3MWUwM2JhMTc2ZiIsImdyYW50X3R5cGUiOiJwYXNzd29yZCJ9.nsXQCdM5Lju5KMEf6PAXmZRHFwOMpu92Uy5JCrpUy5d0B8c9_3B1Pk3XsKJZo7knvEqYnqfpbGIEPtgayaN79Q&web=1