Unable to create user in WSO2 IS via SCIM2 API with external claims - wso2

Im trying to create user with external claims, but something wents wrong.
I added my claims to scim2-schema-extension.config, to external claims and local claims, but API's response for my request is:
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:Error"
],
"detail": "Error in adding the user: testoviy22#mail.ru to the user store.",
"status": "500"
}
In logs i have
: ERR_13735_ELEMENT_FOR_OID_DOES_NOT_EXIST ATTRIBUTE_TYPE for OID comment does not exist!]; remaining name 'mail=testoviy22#mail.ru'
at java.naming/com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3280)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3205)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2996)
at java.naming/com.sun.jndi.ldap.LdapCtx.c_bind(LdapCtx.java:452)
at java.naming/com.sun.jndi.toolkit.ctx.ComponentDirContext.p_bind(ComponentDirContext.java:299)
at java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.bind(PartialCompositeDirContext.java:217)
at org.wso2.carbon.user.core.ldap.UniqueIDReadWriteLDAPUserStoreManager.persistUser(UniqueIDReadWriteLDAPUserStoreManager.java:312)
... 73 more
Local claim
External claim
Request sample:
{
"name": {
"familyName": "Zubenko",
"givenName": "Michael"
},
"password": "qwerty",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"comment": "test"
},
"userName": "testoviy22#mail.ru"
}

Seems you are using an LDAP server as your primary userstore, and that server doesn't support the attribute named "comment"
Refer to the note in https://is.docs.wso2.com/en/latest/references/extend/provisioning/extend-scim2-user-schemas/#map-the-custom-claim
You can use the word "customClaim" (or any other preferred word) as
the Mapped Attribute only when using a JDBC userstore because JDBC
userstores will automatically create a new attribute if it does not
already exist in the user store. However, If you are using LDAP or
Active Directory, you will have to use an attribute that exists in the
user store already.
Change the mapped attribute of the local claim to some valid attribute in the LDAP schema

Related

Get proper usernames to populate on Superset with Azure SSO instead of ID string

I've finally gotten Azure Single Sign-On (SSO) connected to Apache Superset running via docker-compose, following the Flask docs. Users in my company's Azure group can create and access Superset accounts by logging in with Azure and they are assigned roles based on their identity. This is good.
The usernames they get assigned, however, are long Azure ID strings. These are undesirable in displays. Here's what my account looks like on the List Users screen and on my profile:
How can I modify either my Azure application SSO setup or my Superset config to have Superset populate usernames like SFirke for the account usernames, instead of values like 3ee660ff-a274 ... ?
The security part of my config.py looks like this, almost identical to the Flask template:
OAUTH_PROVIDERS = [
{
"name": "azure",
"icon": "fa-windows",
"token_key": "access_token",
"remote_app": {
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET",
"api_base_url": "https://login.microsoftonline.com/TENANT_ID/oauth2",
"client_kwargs": {
"scope": "User.read name preferred_username email profile upn groups",
"resource": "RESOURCE_ID",
},
"request_token_url": None,
"access_token_url": "https://login.microsoftonline.com/TENANT_ID/oauth2/token",
"authorize_url": "https://login.microsoftonline.com/TENANT_ID/oauth2/authorize",
},
},
]
EDIT: Looks like the way to go is writing a custom userinfo retrieval method, there's a template on the Flask page linked above and an example used for Superset in this Github comment. I think I would use a line like "id": me["preferred_username"] or "id": me["upn"], based on the field names in the Microsoft docs.
But Microsoft notes that this value can change over time and should not be used for authorization changes. Since the oid value is immutable, and it is hardly visible to the typical user, I plan to just stick to it.

Getting following error while creating a user in WSO2 IS 5.9.0 using scim API?

My username is mapped to email while creating a user with payload
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"name": {
"formatted": "Careerex Admin"
},
"userName": "careerex.admin#in.aanasonic.com",
"password": "abc!12345",
"profileUrl": "www.gmail.com",
"phoneNumbers": [
{
"type": "mobile",
"value": "9876543210"
}
],
"locale": "Delhi"
}
I am getting following error regarding restrictions of username-
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:Error"
],
"scimType": "invalidValue",
"detail": "31301 - Username careerex.admin#in.aanasonic.com is not valid. User name must be a non null string with following format, ^[\\S]{3,30}$",
"status": "400"
}
Please help how to fix this and create user with same email???
The default configuration available in WSO2 Identity Server enforces the username to be a string with a length of 3 to 30 non-empty characters. Your usecase requires the username length to be more than the default range provided.
To support your requirement, add the following parameters for userstore configuration in the deployment.toml file available at <IS_HOME>/repository/conf as given below.
[user_store]
username_java_script_regex = '^[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$'
username_java_regex='^[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}'
You can provide a suitable regular expression to match your requirement. Note that username_java_script_regex is used by front-end components for username validation.
Refer here for more information.
By default, the username in the WSO2 is not allowed as email. You need to configure the product to support username as email. You can follow this documentation to achieve this

AWS Kinesis: user address in event encoded / encrypted

In my React Native mobile app, I use AWS Amplify to send info about user actions (screen views, button taps, swipes, etc.) by means of Analytics.record(...) to AWS Pinpoint which in turn feeds them into a AWS Kinesis Data Stream. I have created an AWS Lambda Python 3 function that listens to events in this data stream.
Setup has been a breeze, thanks to outstanding documentation and everything works fine - except for one thing:
When a user logs in, I update the Pinpoint Endpoint with the user ID, email address and some more attributes using Analytics.updateEndpoint(...). In the lambda function, I base64-decode the event payload as shown in this sample code and a sample event payload looks roughly like this:
{
"event_type": "_session.start",
"event_timestamp": 1572345161558,
"application": {
"app_id": "<some app ID>",
"cognito_identity_pool_id": "us-east-1:<some pool ID>",
"sdk": {},
"version_name": "<the app version I put in using updateEndpoint(...)>"
... <snipped for brevity> ...
},
"attributes": {},
"endpoint": {
"ChannelType": "APNS",
"Address": "=ABAQRuUDJD ... <some longish binary value> j0eL+69lsY=",
"EndpointStatus": "ACTIVE",
"Location": {
"Country": "US"
},
"Demographic": {
"Make": "iPhone",
"Model": "iPhone X",
"ModelVersion": "13.1.3",
...
"Platform": "ios"
},
"User": {
"UserId": "us-east-1:<Cognito ID of the user that logged in>",
"UserAttributes": {}
},
... <snipped for brevity> ...
},
"awsAccountId": "<my account ID>"
}
The user email address in the "Address" field above is not contained in the Kinesis Data Stream event as plain text, but encoded (or encrypted ?) somehow.
My question: Can anybody tell me how it is encoded / encrypted ? And, ideally, how to get the plain text address ?
I tried to base64-decode it or decrypt it using my default AWS KMS key (and a combination thereof), but no luck.
Alternatively, I could use the (plain text) user ID to look up the email address in the AWS Cognito user pool used to manage auth & auth, but getting it from the event directly would obviously be a lot simpler...
I have searched the web up and down, asked in the AWS-Amplify channel on gitter, but that Address encoding / encryption just does not seem to be documented anywhere...

Google Data Transfer API says completed but nothing has happened?

I'm using the Data Transfer API to programmatically transfer the files owned by user A to user B as part of our exit process.
I look up the email addresses for the two users so that I can retrieve their IDs. I also query the list of data transfer applications to get the application ID for "Drive and Docs".
I pass the built transfer definition to the API and get the following JSON back:
{
"kind": "admin#datatransfer#DataTransfer",
"etag": "\"RV_wOygBiIUZUtakV6Iq44-H_Gw/2M4Z2X_c8OpsyQOJxtWDmIHcYzo\"",
"id": "AKrEtIbF0aAg_4KK7-lHFOpRNPhcgAOWWDEK1HE0zD_EEY-bOPHXuj1rKNrEE-yHPYyjY8vzvZkK",
"oldOwnerUserId": "101496053770427062754",
"newOwnerUserId": "118268322014081744703",
"applicationDataTransfers": [
{
"applicationId": "55656082996",
"applicationTransferStatus": "pending"
}
],
"overallTransferStatusCode": "inProgress",
"requestTime": "2017-03-31T10:50:48.560Z"
}
I then query the transfers API to get an update on that transfer and get the following back:
{
'kind': 'admin#datatransfer#DataTransfer',
'requestTime': '2017-03-31T10:50:48.560Z',
'applicationDataTransfers': [
{
'applicationTransferStatus': 'completed',
'applicationId': '55656082996'
}
],
'newOwnerUserId': '118268322014081744703',
'oldOwnerUserId': '101496053770427062754',
'etag': '"RV_wOygBiIUZUtakV6Iq44-H_Gw/ZVnLgj3YLcsURTSzNm8m91tNeC0"',
'overallTransferStatusCode': 'completed',
'id': 'AKrEtIbF0aAg_4KK7-lHFOpRNPhcgAOWWDEK1HE0zD_EEY-bOPHXuj1rKNrEE-yHPYyjY8vzvZkK'
}
and, indeed, I get a confirmation email that the files have been transferred.
However, if I look in Google Drive for both users, the files have NOT changed ownership. For user B, a new directory has been created with the email address of user A, but it contains no files and user A still owns all of their files.
What have I done wrong or misunderstood?
Thanks.
I had faced the same issue, please provide "applicationTransferParams" with key value.
"applicationTransferParams": [
{
"key": string,
"value": [
string
]
}
]

How to get user attributes (username, email, etc.) using cognito identity id

I have AWS Cognito Identity Pool that is configured with Cognito User Pool as an authentication provider.
Assume I have identity ID of an identity in Cognito Identity Pool (e.g. us-east-1:XXaXcXXa-XXXX-XXXX-XXX-XXXXXXXXXXXX) where this identity has a linked login to a user in Cognito User Pool.
Using identity ID, how can I get the linked user details (email, phone, username)?
The ID Token that you exchange with Cognito federated identity service to get the identity id and credentials already has all user attributes. You do not need an extra call to any service.
It is a JWT token and you can use any library on the client to decode the values. You can read this guide for more information about the tokens vended by Cognito user pools.
Alternatively, you can also use the Access Token to call GetUser API which will return all the user information.
Using REST API
AccessToken
Thought that this could be very helpful to someone as I've spent a lot of time trying to figure out how to get UserAttributes with only accessToken and region ( Similar to this but with REST API ( Without using aws-sdk )
You can get UserAttributes with accessToken using this HTTP request. ( GetUser )
Method: POST
Endpoint: https://cognito-idp.{REGION}.amazonaws.com/
Content-Type: application/x-amz-json-1.1
Content-Length: 1162 // Access Token bytes length
X-Amz-Target: AWSCognitoIdentityProviderService.GetUser
Body: {"AccessToken":"ACCESS_TOKEN"}
And if the accessToken is valid, you should receive example response like the following
{
"UserAttributes": [
{
"Name": "sub",
"Value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
},
{
"Name": "email_verified",
"Value": "true"
},
{
"Name": "name",
"Value": "Jason"
},
{
"Name": "phone_number_verified",
"Value": "true"
},
{
"Name": "phone_number",
"Value": "+xxxxxxxxxxx"
},
{
"Name": "email",
"Value": "xxxx#gmail.com"
}
],
"Username": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
}
AWS cognito-idp list-users has a filter option that allows you to filter based on attribute. 'sub' is the attribute that matches the identity id you are describing.
e.g. at the command line:
aws cognito-idp list-users --user-pool-id us-east-1_abcdFghjI --filter "sub=\":XXaXcXXa-XXXX-XXXX-XXX-XXXXXXXXXXXX\""
This also requires the user-pool-id, which I suspect you have. Additionally, I have no idea how this is implemented or how it performances when filtering a large number of users, but I take custom attributes not being usable in filters as a hint that there is some form of indexing behind the curtain.
I faced the similar issue and after too much of scratching i was not able to find the exact way of pulling out the details. My usecase was to get the details in android APP.
After looking into their AWSMobile client API code. I found below and it is working from me.
Log.i(TAG, "User Details"+ AWSMobileClient.getInstance().getUserAttributes().toString());
Recommendation - Try use AWSMobileclient incase you are using it for Android Development as this is new library that is recommended for development.
Just struggled with this for a while, and the way I got the user name, using Java API is:
identityManager.login(this, new DefaultSignInResultHandler() {
#Override
public void onSuccess(Activity activity, IdentityProvider identityProvider) {
...
String userName = ((CognitoUserPoolsSignInProvider) identityProvider).getCognitoUserPool().getCurrentUser().getUserId();
There is a listener we can initialize that will listen to changes in our authentication state and allow us to have access to the type of authentication event that happened and update the application state based on that data.
With Amplify, the Hub module allows us to do this pretty easily:
import { Hub } from 'aws-amplify';
Hub.listen('auth', (data) => {
const {payload} = data;
if (payload.event === 'signOut') {
console.log('signOut');
} else if (payload.event === 'signIn') {
console.log('A new auth event has happened: ', data.payload.data.username + ' has ' + data.payload.event);
}
});
For those who are looking how to get the value of email parameter in Java programmatically
I assume you have already figured out how to get the needed / all users from the pool.
Say I have ListUsersResult with my all users and say I want to check the email value of the first user:
ListUsersResult allUsers = getAllUsers();
UserType userType = allUsers.getUsers().get(0);
First I can get user's all attributes:
List<AttributeType> attributes = userType.getAttributes();
Then loop through the attributes looking for the one we're interested in (our case email):
for (AttributeType att : attributes) {
if (att.getName().equals("email")) {
// do whatever you want
}
}
Remember that printing in to the console will most probably not work since it is sensitive data. But you can compare it like this:
att.getValue().equals("mymail#mail")
Use this piece of code
GetDetailsHandler detailsHandler = new GetDetailsHandler() {
#Override
public void onSuccess(CognitoUserDetails cognitoUserDetails) {
CognitoUserAttributes cognitoUserAttributes=cognitoUserDetails.getAttributes();
stringStringHashMap=new HashMap<>();
stringStringHashMap =cognitoUserAttributes.getAttributes();
userNumber=stringStringHashMap.get("phone_number");
e1.setText(userNumber);
Log.d("Response"," Inside DEATILS HANDLER");
// Store details in the AppHandler
AppHelper.setUserDetails(cognitoUserDetails);
// Trusted devices?
handleTrustedDevice();
// e1.setText(input.getText().toString());
}
#Override
public void onFailure(Exception exception) {
closeWaitDialog();
showDialogMessage("Could not fetch user details!", AppHelper.formatException(exception), true);
}
};
private void getDetails() {
AppHelper.getPool().getUser(username).getDetailsInBackground(detailsHandler);
}
console.log('username is ' + cognitoUser.getUsername());