I configured Keycloak to authenticate the users of my client and return it's role to my application. The following JSON is the data Keycloak returns with OIDC for my user. In the data, we can clearly see that the field resource_access.test-client.roles is present.
{
....some data..
"allowed-origins": [
"http://localhost:5000"
],
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"test-client": {
"roles": [
"DemoRole"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
....some data..
}
In my application side I used Flask-OIDC to make the authentication and get my user role.
The app configuration was done this way
app.config.update({
'SECRET_KEY': 'u\x91\xcf\xfa\x0c\xb9\x95\xe3t\xba2K\x7f\xfd\xca\xa3\x9f\x90\x88\xb8\xee\xa4\xd6\xe4',
'TESTING': True,
'DEBUG': True,
'OIDC_CLIENT_SECRETS': 'client_secrets.json',
'OIDC_ID_TOKEN_COOKIE_SECURE': False,
'OIDC_REQUIRE_VERIFIED_EMAIL': False,
'OIDC_USER_INFO_ENABLED': True,
'OIDC_SCOPES': ['openid', 'email', 'profile', 'roles'],
'OIDC_VALID_ISSUERS': ['http://localhost:8080/auth/realms/MyDemo'],
'OIDC_OPENID_REALM': 'http://localhost:5000/oidc_callback'
})
The client_secrets.json is
{
"web": {
"auth_uri": "http://localhost:8080/auth/realms/MyDemo/protocol/openid-connect/auth",
"client_id": "test-client",
"client_secret": "40074399-b1b6-442c-9862-68b655ef8dad",
"redirect_uris": [
"http://localhost:5000/oidc_callback"
],
"userinfo_uri": "http://localhost:8080/auth/realms/MyDemo/protocol/openid-connect/userinfo",
"token_uri": "http://localhost:8080/auth/realms/MyDemo/protocol/openid-connect/token",
"token_introspection_uri": "http://localhost:8080/auth/realms/MyDemo/protocol/openid-connect/token/introspect"
}
}
This done, I'm trying to retrieve the role from my user in the following endpoint
#app.route('/private')
#oidc.require_login
def hello_me():
info = oidc.user_getinfo(['resource_access'])
client = info['test-client']
role = client['roles']
The problem is that 'info' is being returned empty. I can access the fields 'email', 'surname' and others, but I can't access 'resource_access', even it being present in the returned JSON. I expected that the sequence of code above could return me the user roles.
What am I doing wrong?
Claim resource_access can be exposed in the access token and/or id token and/or userinfo response. It is not clear from your problem description, where it is exposed exactly. Apparently it is in the wrong place and not where your application code is expecting that.
So fix location of the claim and you should be fine:
lazy option: expose it everywhere (access token and id token and userinfo response)
proper option: read documentation of used library and expose claim only to the right location (access token or id token or userinfo response)
Related
Given a client-side app (written in Angular, but it's not much important) where I use google-api-javascript-client library to authenticate users. In a way described here - https://developers.google.com/sheets/api/quickstart/js:
gapi.load('client:auth2', () => {
gapi.client.init({
clientId: CLIENT_ID,
scope: SCOPES,
discoveryDocs: DISCOVERY_DOCS
}).then(() => {
gapi.auth2.getAuthInstance().isSignedIn.listen(this.onSigninStatusChanged.bind(this));
const isSignedIn = gapi.auth2.getAuthInstance().isSignedIn.get();
if (!isSignedIn) {
gapi.auth2.getAuthInstance().signIn({prompt: 'select_account'});
}
});
});
Now I want to access a backend in AppEngine behind Identity-Aware Proxy (IAP).
I tried naively to pass a token from GoogleUser via http request's authorization header, but it doesn't seem to work (getting 401):
let token = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().id_token;
this.http.get<Config>('https://myservice-dot-myproject.ew.r.appspot.com/api/get',
{
headers: { 'Authorization': 'Bearer ' + token}
});
I guess I need somehow to use OAuth Client ID from IAP.
I found a sample on how to do it with nodejs auth client.
But can't find a way to do it with the client-side google-api-javascript-client lib.
UPDATE:
I found a nice online resource to verify token that I got from GoogleUser.getAuthResponse().id_token - https://oauth2.googleapis.com/tokeninfo?id_token=token (source), it display the following:
{
"iss": "accounts.google.com",
"azp": "my OAuth Client ID that I used in gapi (CLIENT_ID)",
"aud": "OAuth Client ID that I used in gapi (CLIENT_ID)",
"sub": "user id (number)",
"hd": "Google user GSuite domain",
"email": "Google user email",
"email_verified": "true",
"at_hash": "some hash",
"name": "Google user name",
"picture": "an url",
"given_name": "Google user firstname",
"family_name": "Google user lastname
"locale": "en",
"iat": "1615972232",
"exp": "1615975832",
"jti": "87129b6c0f684b0bc7beac9df5e522e6272c13f1",
"alg": "RS256",
"kid": "6a8ba5652a7044121d4fedac8f14d14c54e4895b",
"typ": "JWT"
}
We are using WSO2 SCIM apis to define roles to user and update it.
For role update operation , we are currently adding the new user role(add user to new role group using SCIM api) , and then delete the existing user role (call users SCIM GET request under a GROUP, delete the existing user from the list and use the newly created list as body arguments to call SCIM PATCH request for the GROUP). With this approach , we were able to update roles. But as the user base increased , the above approach of PATCH operation is getting timeout error .(The new role gets updated to user, but the existing role persists as the 2nd api is getting failed).
Below is one solution which i tried out :
Add new role, delete the newly created role inside user details and call PATCH api with the updated roles of user. But then realized on further investigation that roles inside user is readonly and can't be updated using patch/put operations. So i failed in getting a proper solution .
Is there a way to update a single user's role inside the GROUP without using PATCH /Groups endpoint ?
As I have mentioned in the answer https://stackoverflow.com/a/64225419/10055162, the SCIM specification doesn't allow to update the user's group attribute using PATCH /Users/{userId}.
Also, PATCH /Groups/{groupId} may cause performance issues when the group's member count is too high.
WSO2 IS has improved the performance of PATCH /Groups/{groupId} to some extent.
https://github.com/wso2/product-is/issues/6918 - available 5.10.0 onwards
https://github.com/wso2/product-is/issues/9120 - available 5.11.0 onwards
So, if you are using an older version of IS, can you please try with the latest GA release(5.11.0). It may improve the performance.
UPDATED:
You can use SCIM POST /Bulk endpoint to update user's groups by single REST call, instead of having multiple PATCH /Groups/{group-id} calls.
Refer to https://anuradha-15.medium.com/scim-2-0-bulk-operation-support-in-wso2-identity-server-5-10-0-8041577a4fe3 for more details on Bulk endpoint.
example:
To assign two groups (Group1 and Group2) to a user, execute POST https://<host>:<port>/scim2/Bulk with payload similar to the following.
{
"Operations": [
{
"data": {
"Operations": [
{
"op": "add",
"value": {
"members": [
{
"display": "anuradha",
"value": "db15b161-a205-454d-9da1-4a2a0df0585e"
}
]
}
}
]
},
"method": "PATCH",
"path": "/Groups/f707b6cc-91f8-4b8a-97fb-a01c2a79515c"
},
{
"data": {
"Operations": [
{
"op": "add",
"value": {
"members": [
{
"display": "anuradha",
"value": "db15b161-a205-454d-9da1-4a2a0df0585e"
}
]
}
}
]
},
"method": "PATCH",
"path": "/Groups/8c91215f-1b7a-4cdb-87d9-ae29c60d70de"
}
],
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:BulkRequest"
]
}
I am trying retrieve the user list which have locked accounts in WSO2 IS 5.9 version.
I tried after adding account lock attribute to below claims:
http://schemas.xmlsoap.org/ws/2005/05/identity
urn:ietf:params:scim:schemas:core:2.0
urn:ietf:params:scim:schemas:core:2.0:User
urn:ietf:params:scim:schemas:extension:enterprise:2.0:User
I have followed below URL as well to add the custom claim:
https://is.docs.wso2.com/en/5.9.0/develop/extending-scim2-user-schemas/
{ "attributeURI":"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:accountLock",
"attributeName":"accountLock",
"dataType":"boolean",
"multiValued":"false",
"description":"Account lock",
"required":"false",
"caseExact":"false",
"mutability":"readwrite",
"returned":"default",
"uniqueness":"none",
"subAttributes":"null",
"multiValuedAttributeChildName":"null",
"canonicalValues":[],
"referenceTypes":[]
}
But still i am not able to get the accountLock attribute in response to GET Users API of scim2.
Response
"totalResults": 10,
"startIndex": 1,
"itemsPerPage": 10,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"emails": [
"divya#abc.com"
],
"meta": {
"created": "2020-06-25T07:49:35.465Z",
"lastModified": "2020-06-25T11:20:13.482Z",
"resourceType": "User"
},
"name": {
"givenName": "guest",
"familyName": "guest"
},
"groups": [
{
"display": "Application/sp1"
},
{
"display": "Application/sp2"
},
{
"display": "Application/Read"
}
],
"id": "9ffbed2e-3703-470c-a2c8-e738f4c09709",
"userName": "guest12"
}
]}```
The following reasons may cause to accoutLock attribute does not appear in SCIM2 GET user response.
You might missed to add the new attribute ( "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:accountLock") as a sub attribute of urn:ietf:params:scim:schemas:extension:enterprise:2.0:User object. (Point 3 in https://is.docs.wso2.com/en/5.9.0/develop/extending-scim2-user-schemas/#extending-the-scim-20-api.
"subAttributes":"accoutLock verifyEmail askPassword employeeNumber costCenter organization division department manager")
"attributeURI":"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
"attributeName":"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
"dataType":"complex",
"multiValued":"false",
"description":"Enterprise User",
"required":"false",
"caseExact":"false",
"mutability":"readWrite",
"returned":"default",
"uniqueness":"none",
"subAttributes":"accoutLock verifyEmail askPassword employeeNumber costCenter organization division department manager",
"canonicalValues":[],
"referenceTypes":["external"]
}```
The mapped attribute of the added custom claim (https://is.docs.wso2.com/en/5.9.0/develop/extending-scim2-user-schemas/#add-the-custom-claim) should be an existing attribute in LDAP schema if you are using the default LDAP userstore. (However, if you have done this mistake you won't be able to update/add claim value. It gives One or more attributes you are trying to add/update are not supported by underlying LDAP for user: error)
The response of SCIM2 GET users doesn't contain the attributes which don't have a value. Thus, set true/false to the claim value.
Moreover, it is enough to add the new attribute to urn:ietf:params:scim:schemas:extension:enterprise:2.0:User claim dialect. Follow steps in https://is.docs.wso2.com/en/5.9.0/develop/extending-scim2-user-schemas/
I use the JavaScript AWS SDK for MFA setup and have 2 issues:
First, I update phone number (phone_number attribute with updateUserAttributes method).
It updates but returns empty object instead of (according to docs):
{
"CodeDeliveryDetailsList": [
{
"AttributeName": "string",
"DeliveryMedium": "string",
"Destination": "string"
}
]
}
Second, I am trying to send user a verification code with getAttributeVerificationCode with the following payload:
const params = {
AccessToken: auth.accessToken,
AttributeName: 'phone_number'
}
and I am getting
CustomMessage failed with error
Cannot read property identity of undefined
as error. Any ideas?
For the ones who come across same problem, we could solve it by using cognitoUser.updateAttributes instead of cognitoidentityserviceprovider.updateUserAttributes contrary to the official docs. AWS, especially cognito is premature and lack of docs is another issue for the ones who are considering to use.
AWS is expecting strings, maybe the token is getting passed incorrectly here...
const params = {
"AccessToken": auth.accessToken.toString(),
"UserAttributes": [
{
"Name": "phone number",
"Value": "(555)555-5555"
}
]
}
And here...
const params = {
"AccessToken": auth.accessToken.toString(),
"AttributeName": "phone number"
}
I'm unable to get a list of my campaigns using Facebook Graph API
Response for /me/adaccounts
{
"data": [
{
"account_id": "123456789000001234",
"id": "act_123456789000001234"
}
],
"paging": {
"cursors": {
"before": "AAAAaaaBBBBcccc",
"after": "AAAAaaaBBBBdddd"
}
}
}
/123456789000001234/campaigns returns
{
"error": {
"message": "Unsupported get request. Object with ID '123456789000001234' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api",
"type": "GraphMethodException",
"code": 100,
"fbtrace_id": "EilRrOk1CEb"
}
}
Note that id's have been changed to dummy-values.
The token is for a system user and the ad account have been assigned to the user (role: admin). Token contains following scopes: read_page_mailboxes, rsvp_event, ads_management, ads_read, read_insights, manage_pages, publish_pages, pages_show_list, pages_manage_cta, pages_manage_instant_articles, business_management, publish_actions
What am I doing wrong?
Had to use id: act_123456789000001234 instead of account_id: 123456789000001234 so the request becomes /act_123456789000001234/campaigns. Also had to create a Facebook App, add Marketing API and assign to that an Ad Account, then create a token via the app instead of creating a token from the Business Manager.