Is there any standard scope claim in OpenID Connect, JWT or OAuth?
In the IdentityServer 4 documentation, the there is a "scope" which is a space-separated string.
{
"client_id": "mobile_app",
"sub": "123",
"scope": "read write delete"
}
But from my IdentityServer 4 instance, I get a "scope" claim in the access token which is a array of strings.
{
// ...
"client_id": "mobile_app",
"sub": "123",
"scope": [ "openid", "profile", "email", "offline_access" ],
"amr": [ "pwd" ]
}
In the OpenID Connect Core 1.0 specification, I do not see "scope" listed as a claim.
In the RFC 7519 JSON Web Token (JWT) specification, I do not see "scope" listed as a claim.
The scope claim was standardized by the Token Exchange RFC. According to the spec it should be a JSON string, with a space-separated scope tokens.
The value of the "scope" claim is a JSON string containing a space-separated list of scopes associated with the token...
Most providers supports the AT+JWT token type and in it is specified that it should include a scope claim:
JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens
It says:
If an authorization request includes a scope parameter, the
corresponding issued JWT access token MUST include a scope claim as
defined in section 4.2 of [TokenExchange].
All the individual scopes strings in the scope claim MUST have meaning
for the resource indicated in the aud claim.
Related
I am trying to implement my own server authentication (email, password) along with Facebook, and Google login. I would like to list what I have searched. Facebook login only returns an access token while Google login returns an access token and an id token.
I am planning to create my own JWT token in the backend, so which parameters (id token/access token) should be passed to my backend server to verify if the end user is logged in using Facebook or Google? I have some confusion about whether the access token is being used for authorization instead of authentication.
The token you get from google and facebook contain user data eg email, profile image etc you need to decode them.
Assuming email is unique in your db then you can query if exists and generate tokens on success.
example on how to decode google tokens in python
TLDR
from google.oauth2 import id_token
from google.auth.transport import requests
# (Receive token by HTTPS POST)
# ...
try:
# Specify the CLIENT_ID of the app that accesses the backend:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
# Or, if multiple clients access the backend server:
# idinfo = id_token.verify_oauth2_token(token, requests.Request())
# if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]:
# raise ValueError('Could not verify audience.')
# If auth request is from a G Suite domain:
# if idinfo['hd'] != GSUITE_DOMAIN_NAME:
# raise ValueError('Wrong hosted domain.')
# ID token is valid. Get the user's Google Account ID from the decoded token.
userid = idinfo['sub']
except ValueError:
# Invalid token
pass
Response
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}
I'm using the Keycloak Admin Rest API and would like to create a new client scope and get its id.
To create the client scope I use this endpoint:
http://localhost:8080/admin/realms/master/client-scopes
Body
{
"attributes": {
"display.on.consent.screen": "true",
"include.in.token.scope": "true"
},
"name": "example",
"protocol": "openid-connect"
}
This endpoint doesn't return a result but I need the ID.
To get the ID I could get all client scopes and find the scope with the matching name however I would have thought there would be a simpler way.
E.g. GET http://localhost:8080/admin/realms/master/client-scopes then filter through the results to find a matching name.
Is it possible to get a client scope by name?
Is it possible to get a client scope by name?
Unfortunately, not, which is a pity because the 'name' is unique. If you look at the keycloak Rest Admin API you can see the followings GET for the client-scopes:
GET /{realm}/client-scopes
and
GET /{realm}/client-scopes/{id}
And none of those endpoints accepts as parameters 'name'.
Notwithstanding, as #csbrogi and #Jan Garaj have pointed out in the comment section, since you:
(..) create a new client scope and get its id.
You can retrieve the ID of the client-scope that was just created from the header location:
In the Keycloak, usually POST methods returns 201 or 200 OK without body as experienced. Thus, you cannot get the ID directly from response. What you can do is; assign a ID while creating scope as below body and you simply will have it.
{
"id": "da5a68f1-058c-481a-bf84-deb95b1f21aa",
"attributes": {
"display.on.consent.screen": "true",
"include.in.token.scope": "true"
},
"name": "example",
"protocol": "openid-connect"
}
I am working on script where I need to find if PAT has full scope or not.
I found following information In Microsoft Docs -
GET https://vssps.dev.azure.com/{organization}/_apis/tokenadmin/personalaccesstokens/{subjectDescriptor}?api-version=6.0-preview.1
Using this API I can find all the PATS and their names , scope and more details for particular user.
I do not want to pass PAT name in script and then find out scope for it.
I want to use PAT token and return scope for the given PAT token
Is there any API available to achieve this ?
I do not want to pass PAT name in script and then find out scope for it.
I want to use PAT token and return scope for the given PAT token
I am afraid there is no such way to return PAT scope via PAT token instead of PAT name at this moment.
Just as return of the REST API Personal Access Tokens - List:
{
"clientId": "00000000-0000-0000-0000-000000000000",
"accessId": "439729fa-be4e-49b2-8530-263cf053d786",
"authorizationId": "a451306e-621d-4a6c-8c54-9096493a40f9",
"hostAuthorizationId": "00000000-0000-0000-0000-000000000000",
"userId": "c1b9603c-da3a-410e-9e59-074dcee61dcc",
"validFrom": "2021-01-07T00:00:00",
"validTo": "2021-02-06T00:00:00",
"displayName": "TestPATA1",
"scope": "app_token",
"targetAccounts": [
"c519b80d-5d71-46b3-a8e0-3edf8c026ea2"
],
"token": null,
"alternateToken": null,
"isValid": true,
"isPublic": false,
"publicData": null,
"source": null,
"claims": null
},
The response body does not contain the value of the PAT token, therefore, we could associate the value of the PAT token with each PAT.
On the other hand, when we create the PAT, we will receive the message:
Warning - Make sure you copy the above token now. We don't store it and you will not be able to see it again.
For security reasons, Azure devops does not save the PAT value we created. Therefore, there will not be any attributes such as saving or recording the PAT value in Azure devops, so we could not use PAT token as a judgment condition.
I'm essentially doing something very similar to this post. I would like to be able to verify some JWT tokens that have been signed on an IdentityServer, and there are a few details that I haven't figured out yet. Here is an example token:
eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiZjM5OWIwYjRkNzY3OTE5MDFlYzlmNTUxNTZkMzdlIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1Mjc4OTA2MDAsImV4cCI6MTUyNzg5NDIwMCwiaXNzIjoiaHR0cDovL2NvbW1hbmRjZW50ZXI6NTAwMCIsImF1ZCI6Imh0dHA6Ly9jb21tYW5kY2VudGVyOjUwMDAvcmVzb3VyY2VzIiwiY2xpZW50X2lkIjoiY29tbWFuZGNlbnRlciIsInN1YiI6ImU3NzY4MjEyLTdhMGYtNDA4YS04YzlmLWZmNDRmOTVlNzc2ZSIsImF1dGhfdGltZSI6MTUyNzg5MDYwMCwiaWRwIjoibG9jYWwiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIl0sImFtciI6WyJwd2QiXX0.N6j_8Mbc-WAZInLnhauBS_dC6my3ggJEFGNBuuanJXGG5Q1mL7K9KZ11cgxrWQEp6NRS07bZrh02qA0Hcd0pLJzg0xB49CR-kFlA8PWdZ-wnf1U4VGq7ZZY2PaxccqextF-s3V-ObEsnPq7k1csTBM_lBW5u4m907q3zcHfPtW9RNz3kELKSuW1vMOWksrOOaJO3UGAPJgRcFjlc5imPykKQVCiAO9UV1nuNUHOLOu4XDim-f3YHLU24J-vbgxkqdUtgs4Xm43b3AplYrkN_TJ0ba5demtnQNd5No0s6bkqkuPvVGz2G3MD5tWkQVnu7kV7GNfTOvJlInCkDOE6few
Taking this over to https://jwt.io/ you can see that the token parses out to be
{
"alg": "RS256",
"kid": "0bf399b0b4d76791901ec9f55156d37e",
"typ": "JWT"
}.
{
"nbf": 1527890600,
"exp": 1527894200,
"iss": "http://commandcenter:5000",
"aud": "http://commandcenter:5000/resources",
"client_id": "commandcenter",
"sub": "e7768212-7a0f-408a-8c9f-ff44f95e776e",
"auth_time": 1527890600,
"idp": "local",
"scope": [
"openid",
"profile"
],
"amr": [
"pwd"
]
}.
{SIGNATURE}
I've seen 2 main ways in which tokens are signed. One is just using some passpharase that everyone magically has to know in order to verify the token. We don't want to have to manage updating multiple clients when a passphrase changes, so this is not an option for us. The other way is to use essentially a PKI method much like how HTTPS keys are exchanged and authenticated using X509 certificates. I have a few questions about this and this particular example:
1. Why isn't the 3rd and final section of the token Base64 encoded? I'm guessing its Base64Url, is that right? The rest of the segments use Base64, why not this one as well?
2. We would like to use essentially SSL certificates for signing and I presume this example token has done the same, but how does the receiver know which public certificate it should fetch in order to validate this token? Shouldn't the certificate serial number be provided?
3. Why is this signature so big? This seems like way to many bytes for just a signature, is there other data packed inside?
I'm trying to understand JWT tokens usage but I'm getting lost on the theorycal part.
I have some questions about JWT Tokens structure, in order to make this question a sort of documentation for new users, providing it with a logic order, I will write them in bold below as long as I list a sample JWT content.
I will also summary them in the end of the question
A "classic" JWT token is composed as follows:
[HEADER].[PAYLOAD].[SIGNATURE]
In detail:
HEADER
{
"alg": "HS256",
"typ": "JWT"
}
Which contains the following fields:
ALG = Encryption algorythm (using the default HS256 could be fine)
TYP = simply tells that it's a JWT
PAYLOAD
{
"sub": "1234567890",
"name": "MrJohnDoe",
"iat": 1516239022
}
SUB = Is an OPTIONAL parameter. It's the subject of the token. (credits: see #cassiomolin answer)
According to: Where to store user id in jwt, it looks like you can use it to store your user ID in it.
NAME = The username
IAT = Token creation date and time, expressed in unix timestamp. (Thanks to #jps and #JeanRostan in the comments below)
SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
SECRET = Unique key known just by the server. To not confuse with the current user password, which should never be used for this! (thanks to #jps in the comments below)
What is sub? Can you please provide me an example of what it could be in a common usage?
The sub claim identifies the principal that is the subject of the JWT. In other other, it can hold the username of the user who you issued the token to.
From the RFC 7519:
4.1.2. "sub" (Subject) Claim
The sub (subject) claim identifies the principal that is the
subject of the JWT. The claims in a JWT are normally statements
about the subject. The subject value MUST either be scoped to be
locally unique in the context of the issuer or be globally unique.
The processing of this claim is generally application specific. The
sub value is a case-sensitive string containing a StringOrURI
value. Use of this claim is OPTIONAL.