Conversion from "id" to "resourceName" for GoogleContactEntry to Person - google-people-api

I have already stored google contact entries in my local database. I am migrating my code from contacts api to people api. To retrieve a single contact in contacts api {id} was required. But in case of people-api it is needed to pass "resourceName(eg:people/c2134122417240780462)" in request path to fetch single contact.
But as I have already stored ids in my local, how can I get resourceName using Id(stored locally) to perform update/delete operations?

Related

How to send OTP to a custom to a user in custom userstore (The database has only one table)

I have made a custom userstore by overriding the UniqueIDJDBCUserStoreManager class, based on this article https://nishothan-17.medium.com/custom-user-store-manager-for-wso2-identity-server-5-11-0-6e23a4ddf1bb . My database has one table which has the username, password, email, name, and phone number.
I was able to authenticate successfully. However, I am unable to send the OTP to the users phone number. Can anyone please guide me on how to send OTP to the user? Which properties do I have to set or override? Any help would be highly appreciated.
I could not find any documentation on this so far.
In order to send the SMS OTP to the user, there should be a valid mobile number in the user's profile.
For that you need to update the mobile claim's mapped attribute accordingly.
Refer to https://is.docs.wso2.com/en/latest/guides/dialects/edit-claim-mapping/ and go to mobile claim configs. Then update the mapped attributes section.
If you connect the custom userstore as your PRIMARY userstore, change the Mapped Attribute to the DB table's column name(phone number as per the question) respective to the PRIMARY userstore domain.
If you are connecting this custom userstore as a secondary userstore, add another mapped attribute for the secondary userstore domain and put the DB table's column name.
NOTE: Since you have only one table in the userstore and mobile number is available as a column in that table I mentioned to use that column name as the mapped attribute. Then you have to add additional DB queries under advance configurations to retrieve that data from DB.
Then, you have to override public Map<String, String> getUserPropertyValuesWithID(String userID, String[] propertyNames, String profileName) throws UserStoreException method in your custom userstore manager. You have to invoke your custom DB query inside this overridden method to retrieve the user attributes.
Here is the reference to the default uniqueIDJDBCUserstoreManager's method implementation:
https://github.com/wso2/carbon-kernel/blob/09b67404ec8f4dc2e19d0d730f33c91441c1c63b/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/jdbc/UniqueIDJDBCUserStoreManager.java#L437
Once http://wso2.org/claims/mobile claim value of the user is requested in SMS OTP flow, the Abstractuserstore manager resolves the mappend attribute of the claim and handed over to the relevant userstore manager to resolve the properly value.
I guess you are referring to the SMS-OTP as a second factor authentication. You can refer to this document [1].
And do you have any error trace to see if there are any specific issues to fix?
Refer:
[1] https://is.docs.wso2.com/en/latest/guides/mfa/2fa-sms-otp/

Wso2 Identity Server 5.8.0: custom claim attribute in Create User by Scim service

In my WSO2 Identy Server (v5.8.0), i have added one custom attribute named XXX.
Then, in my web client application, I invoke /scim2/Users service to create new user inside IDS.
I successfully create user with correct name, surname, email, phone number and so on, but my custom field is not updated in my user content store.
By other hand, if I update field by data entry and read my user from IDS, I can see my custom attribute XXX correctly.
Can someone help me ?
One of the following reasons could be caused not to update custom attributes via scim2/Users endpoint.
Once you add a new local claim and if you want to access/modify its value using SCIM endpoint it should be mapped to scim claim dialect. Follow the steps in extending scim user claims doc in https://docs.wso2.com/display/IS580/Extending+SCIM+2.0+User+Schemas
If the above step is correctly configured, check the request payload whether the attribute is correctly defined in the payload. If the attribute is not defined in the expected format, WSO2 IS ignores those attributes.
When you trying to update the value via login to the management console and view the user profile through the management console doesn't involve the SCIM APIs. You are directly updating the local claim in the WSO2 local claim dialect. If you have followed the doc mention is step 1 and that attribute has a value, GET /scim2/Users/{user-id} should return the attribute in the response.

Preventing malicious actions in dynamo DB accessed via lambda over REST

Situation: There is a dynamo DB containing a column with the username, one with a unique ID, and the data for each post submitted via an Angular frontend (REST) that triggers the lambda function over AWS API gateway.
Angular frontend --> AWS API Gateway (authenticate) --> Lambda function (write to) --> DynamoDB
Challenge: While only allowing authenticated requests to the API there are not user details (only the token)
'identity': {'cognitoIdentityPoolId': None, 'accountId': None, 'cognitoIdentityId': None, 'caller': None}
according to the AWS documentation, there is no way to obtain the user who has triggered the lambda function. Therefore currently I have to rely on the value provided via Angular (which can be manipulated)
I want to ensure that no evil user alters the username (provided by the frontend) by submitting HTTP posts with postman or another tool and therefore overrides or creates entries on behalf of another user. Or any other idea, how to create records in a table (via lambda) in a way that the primary key goes to a particular user, while preventing other authenticated users to submit requests on his behalf
It turns out, that the amplify SignUp API generates a persistent UUID for a user, and uses it as the immutable username attribute internally. This UUID has the same value as the sub claim in the user identity token.
Therefore I am now using:
let userID = (await Auth.currentUserInfo()).attributes.sub;
in the frontend, as the UUID is not predictable, and require the ID for all reads and writes.
See: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes.html

Save AWS Cognito Users in DynamoDB

I recently started experimenting with AWS AppSync but I had some questions around AWS Cognito.
I would like for users to be able to authenticate with Facebook but I need their profile picture, name and email as data for my public user profiles in my app. So far, I noticed Cognito integrates with Facebook Auth but it does not allow access to the user information and this info does not get saved in a DynamoDB table.
My question is, how can I create a new User in DynamoDB when Cognito receives a new sign in, or return an existing user/id when the user already exists in the db.
I was trying to achieve the same a few weeks ago.
After reading the docs for hours, I realised that Cognito may not help us in regards to the data that comes back from FB or how to save it.
I ended up doing the following:
(1) Using FB-SDK, pulled in the user data.
(2) Invoked a Lambda function that saved this data (like FB_id,etc) to DynamoDB.
(3) If user logged in again, their FB_id (or email) was used to check against DynamoDB entries to retrieve their data.
If Cognito is able to help us and I missed it somehow, I would love to know.
Happy Coding!
You could use custom attributes and federating user from Facebook in your user pool to achieve this. Here are the steps at high level to do this.
You will first have to define custom attributes for the profile information you want to save in each user profile.
Define attribute mapping to link the custom attributes to Facebook attributes you want to save.
Build you application using Cognito hosted pages and federation to allow your users to log in using Facebook.
After this, on each new user log in in your app a new user is created in your user pool with all the attributes that were defined in attribute mapping and values which Cognito gets in the Facebook token. Your app will get these attribute values in the IDToken issued after authentication and you app can use these.
Additionally, if you want to store these attribute values outside of Cognito user pools profile, like your own DynamoDB table, you can configure a PreSignUp trigger in the pool which will be invoked on all new user creations. You can export the user attributes from this trigger to any database of your choice.
Hope this helps.
AWS AppSync allows you to access information in the GraphQL resolver which you can choose to store in a DynamoDB table. In your case for data coming from a Facebook profile you could pass this as arguments to a GraphQL mutation or in a header to AppSync which you can then access in the resolver via $ctx.request.headers.NAME where NAME is your header name. Then you could simply choose which attributes you want to write to DynamoDB for that user as part of the mutation. More information is in the reference guide here: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html
Since you also asked that you'd like to do a check first to see if the user is already in the DDB first you could just do an existence check first:
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"userId": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
"condition": {
"expression": "attribute_not_exists(userId)"
},
}
This checks against the username from Cognito User Pools. If you were using the Cognito Federated Identities feature it would be ctx.identity.cognitoIdentityId. If the record is already there the response that comes back will tell you which means the user is already present. You could also transform the returned message in the response mapping template by looking at $ctx.result with a conditional statement and either building the JSON response by scratch or using one of the $util.error() methods in the guide above.
Finally as you mentioned that you'll have public profile data, you might want to mark this on certain records for control. In AWS AppSync you can filter GraphQL responses on authorization metadata such as this. You would just have an attribute (aka column) on the DynamoDB record marked 'public' or 'private. Then your response template would look like so:
#if($context.result.public == 'yes')
$utils.toJson($context.result)
#else
$utils.unauthorized()
#end
You can see more examples of this here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#public-and-private-records

Recording Google Analytics Goal by API

Is it possible to use userID and the API to record a user having done an event (i.e. reached a goal) by API?
For example, if I set up my GA installation to record userID for logged in users, but the Goal I want to record is something that happens when the user is offline.
Can I use an API somehow to tell Google "User 001 completed Goal X"?
Or, alternatively, can I pull a unique identifier from a user's cookie, store it on my server side linked to the user id, and fake a js call back to Google once the goal is reached, as if the user were viewing a success page?
You can fetch the client id from the cookie. Google recommends to use their get function:
ga(function(tracker) {
var clientId = tracker.get('clientId');
});
as
developers should not directly access the cookie analytics.js sets as
the cookie format might change without warning.
You can then send an event or virtual url using the measurement protocol and set up a goal based on that url or event (btw. there is nothing "fake" about it, this is exactly the thing the measurement protocol is supposed to cover).
The caveat is that the data will probably end up in a new session, so the original source might get lost (that's an issue if you do advertising).
Another approach, if your users are usually logged in, would be the User-ID feature (despite it's name it does not ID individual users, but it allows to collect user data across devices as long as an unique ID is sent per user from each device. The Id is not exposed in the interface).
You would again use the measurement protocol but this time send along the user id (you still need to send a client id, but it will be overwritten by the user id). If you enable session unification the logged-in visits of the users (and your measurement protocol calls) will be stitched together into a user-level reporting (this required a special data view which will include only data from visits that have a User Id set). Unlike the client id, which is generated by the Google Analytics Javascript code, the User ID is generated on your server and passed in to GA.