Creating users, and grants - tapkey

I'm creating users and issuing grants to them. I have a limitation with token exchange since these users belong to a different ownerAccount.
I'm doing something similar to what is described here https://developers.tapkey.io/mobile/embedded/getting_started/#creating-a-user but on a server and not mobile.
My challenge is that the ownerAccount to which the user should be created (the one which has the lock for which I want to make grants is different from my account(which has the identity provider) so I get an error, is it possible to create users using authorization code as a mode of authentication?
try {
const user = await axios.put(
`${this.baseUrl}/owners/${this.ownerAccountId}/identityproviders/${this.provider}/users`,
{
'ipUserId': details.userId
},
{
headers: {
'Authorization': `Bearer ${token}`
}
}
)
// create a new contact for the user created above
const contact = await this.createContactForUser(token, user.data.ipUserId)
// create grant for contact created above
await this.createGrantForContact(token, contact.id, details.lockId)
return user.data.ipUserId

As far as I understood from previous questions, you are using authorization code
flow and not token exchange. In that case no identity provider is involved as you are using Tapkey credentials directly.
If you have retrieved an access token from authorization code flow, then you use this one to create contacts and grants with default (= tapkey) identity provider.
Contact or smartphone user works as a connector between owner account and an actual user, identified by an email. Grants are then created for the contact and not the user directly.
For instance, if you create a contact for alvin#somedomain.com and assign the grant to him, it doesn't matter if the user with such an email already exists. He will receive an email about grants being assigned to him and it's up to the user to register the Tapkey account or not.
So in your case, you should create a contact with required identifier (email address)
https://developers.tapkey.io/openapi/tapkey_management_api_v1/#/Contacts/Contacts_Put
and then create grants for this contact
https://developers.tapkey.io/openapi/tapkey_management_api_v1/#/Grants/Grants_Put

Related

No emails are sent to the added and granted user, nor does the user see any locks via the tapkey app while the grants for looks are set

I tried to add a user using the Web API via client credentials and via identity provider. Neither resulted in the invited user receiving an email or seeing the granted lock in his app.
I called /api/v1/Owners to get the owner account's ID for the locks I want a new user to grant access for.
I created a new contact by posting to /api/v1/Owners//Contacts only setting email as identifier (not posting any other data) and using the ownerAccountId from step 1
With the newly created contact id from step 2, ownerAccountId from step 1 and boundlock id I did a put request to /api/v1/Owners//Grants
This resulted in a 200 response, but the new contact did not get any notify or invite email.
When I login to my.portal.nl as owner of the lock I do see the the added user as smartphone user with correct lock and validFrom and validBefore
I expect the invited user in step 4 to be emailed. What am I missing? In your comment you say : Generally speaking, Tapkey will usually not send emails to users.
But how do new users get notified about new locks the can open?
Via the API I do see the users and grants are actually added. I have checked spam folders, but no emails.
When I register as one of these user by using the emailadress I setup as identity and login into the tapkey app, still no locks.
The client ID I'm using is c2f11e47604639323320d08f8e4038f4 and the owner account id is e12e4145-3afb-45ae-81f5-2cdd57d89fb5
I will just summarize what was already explained by Markus in his answer:
Regarding the question about the email:
User will not be informed by email if you create a grant for him.
Regarding the permissions:
If you have created permissions for an user with an identity provider tapkey then these grants are visible for the user once he logs in into the Tapkey app and navigates to his smartphone keys.
If you have created permissions for an user with your own identity provider, these are not displayed in the Tapkey app for a granted user and you need to implement your own application to handle these keys.
We had a look on the grants you have created and as you correctly said, they were created successfuly. All, but one, have been created with your own identity provider and therefore they are not visible in Tapkey app for the granted user. Due to the privacy reasons, I don't want to share anymore details regarding your data here.

Unable to confirm the user registration via AWS SDK

The AWS documentation for JS SDK says:
Force Change Password
The user account is confirmed and the user can sign in using a temporary password, but on first sign-in, the user must change his or her password to a new value before doing anything else.
User accounts that are created by an administrator or developer start in this state.
But if for such a user I try to call forgotPassword method of SDK, it errors saying something like: Password cannot be reset in the current state.
SO how can I complete the registration of a user (created by admin in IAM) from my website. Which is the SDK method that should be called ?
Setting up an Auto Verify Lambda Trigger on the Pre Sign Up Trigger will allow for the user to be a confirmed state, which may get you to the point you are looking for?
Lambda -> Node.js
Give it an appropriate Title
Place the below value in the code:
exports.handler = (event, context, callback) => {
// Confirm the user
event.response.autoConfirmUser = true;
// Set the email as verified if it is in the request
if (event.request.userAttributes.hasOwnProperty("email")) {
event.response.autoVerifyEmail = true;
}
// Return to Amazon Cognito
callback(null, event);
};
Save
Then Select newly created trigger in General Settings -> Triggers -> Pre sign-up
We can do this,
I previously answered mongodb to aws cogniton migration question.
Go through step by step. I explained that the user's created by admin need to change the password(forgot password) but there's still another way to do it. Checkout my answer,
Some content from my answer,
AdminCreateUser:
Create a new user profile by using the AWS Management Console or by calling the AdminCreateUser API. Specify the temporary password or allow Amazon Cognito to automatically generate one.
Specify whether provided email addresses and phone numbers are marked as verified for new users. Specify custom SMS and email invitation messages for new users via the AWS Management Console.
Specify whether invitation messages are sent via SMS, email, or both.
After successful user creation,
authenticate user using same user credentials Use: SDK calls InitiateAuth(Username, USER_SRP_AUTH)
After success of initateAuth, amazon Cognito returns the PASSWORD_VERIFIER challenge with Salt & Secret block.
Use RespondToAuthChallenge(Username, , PASSWORD_VERIFIER)
Amazon Cognito returns the NEW_PASSWORD_REQUIRED challenge along with the current and required attributes.
The user is prompted and enters a new password and any missing values for required attributes.
Call RespondToAuthChallenge(Username, , ).
After successful password change user can be able to login using same credentials which admin created.
Refer: Unable to confirm the user registration via aws

Are there universal Cognito Ids for AWS regardless of sign in?

I've been wrapping my head around AWS Cognito, and can't seem to find a clear answer on this one.
Here is our situation: I have a react-native mobile application (using aws-amplify and it uses three different identity providers:
AWS User Pools
Facebook
Google
I know that user pools are a method to manage, create, and sync users across platforms. Within those user pools, each user has GUID assigned to them called sub, short for subject.
I also know that if I use a third party, say Facebook, to sign in, the identity pool will get the third party user, or the user pool, temp access to the AWS services (say dynamo db).
We have another legacy database of previous info, and we want to have a matching process to assign the user to. So, if user1 logs in, they correspond to our old website with user_one in the legacy db, and we want to link up their data and save it for reference later.
My question is, in the identity pool that all 3 methods access, is there a universal GUID or ID that I can associate with each user regardless of sign in type, and record in a DB? And how do I get it using react-native?
Here is what I have tried:
Auth.signIn(username, password)
.then(user => {
// etc
User returns the user_poolId, clientId, and no identity pool info.
With a federated (FB, Google) sign in:
Auth.federatedSignIn('facebook', {
token: data.accessToken.toString(),
expires_at: data.expirationTime,
}, result)
.then(data => {
let user = {
id: data._identityId,
};
This gives me the _identityId. I'm hoping to get a value similar to this for the user pool signin.

How to retrieve idtoken from AWS Cognito who logged via Google/Fedarated Login

I've set up an application where users can register to my site/web application. Where
A.) A User can either join the site via registering their email/password combination and these users will be registered inside a Cognito User Pool.
B.) A User can join the site via logging in with Google/Facebook.
Bullet point A works as as expected. The user will submit their username and password, they will be able to login and they will receive the ID Token, AccessToken, and other information necessary as a response(I'm using aws amplify where it supeseded cognito javascript libraries). Now, when these users access a protected resource on API Gateway that has a cognito_authorizer enabled they will simply pass in
"Bearer " And they will be able to access
Where the is ID Token.
Now, for case B.
I am now able to login via social provider. I was able to configure all the necessary configurations in both google developer console, and registered google as federated entities.
Now, Thanks to aws amplify, I can perform a federated sign in by passing in the id token, and expires_at value that I have received from the google login.
However the only values I am able to received as a response from cognito is the CognitoIdentityCredentials
(https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityCredentials.html)
There is no access token, refresh token, and other necessary information.
Question is. Is it possible for federated sign in to retrieve an access token, and idtoken that is generated by cognito, and use that as token to be passed in as a header whenever I perform a request where a resource has a cognito_authorizer for users who joined my site via social login? Or am Missing certain steps to perform federated login that will return idtoken,and access token which is generated by cognito?
Here's the sample code I'm using
const profile = res.getBasicProfile();
const { id_token, expires_at } = res.getAuthResponse();
const user = {
email: profile.getEmail(),
name: profile.getName()
};
console.log(id_token);
Auth.federatedSignIn(
// Initiate federated sign-in with Google identity provider
'google',
{
// the JWT token
token: id_token,
// the expiration time
expires_at
},
// a user object
user
).then((a) => {
// ...location.reload();
console.log(a);
console.log(Auth.currentUserPoolUser());
});
And this is only the value I receive.
const getIdToken = async() => {return (await Auth.currentSession()).getIdToken().getJwtToken()}

initialize amazon aws cognito client via BasicAWSCredentials vs CognitoAWSCredentials

What is the difference between these two approaches of initializing a new AmazonCognitoIdentityClient?
AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(
new BasicAWSCredentials("access_key_id", "secret_access_key")
);
identityClient.GetOpenIdTokenForDeveloperIdentity()
-
AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(
new CognitoAWSCredentials ("IDENTITY_POOL_ID", "REGION_NAME");
);
identityClient.GetOpenIdTokenForDeveloperIdentity()
Although most examples on the internet show BasicAWSCredentials being used to instantiate a CognitoIdentityClient, but the method signature in the doc says it accepts AWSCredentials class - both BasicAWSCredentials as well as CognitoAWSCredentials are subclasses of the AWSCredentials class. Hence, i am assuming both should be working normally i guess???
I am trying to understand how will this difference, impact the following:
privileges,
timeouts,
etc?
API reference for cognitoIdentityClient constructors is here: http://docs.aws.amazon.com/sdkfornet/v3/apidocs/index.html?page=CognitoIdentity/TCognitoIdentityCognitoIdentityClient.html&tocid=Amazon_CognitoIdentity_AmazonCognitoIdentityClient
In client device you should instantiate AmazonCognitoIdentityClient client using CognitoAWSCredentials. Using STS service, AWS client will obtain temporary credentials that will let the client assume the role you previously defined in your identity pool. Typically this role would have very limited access to your AWS resources. (S3 upload to a specific bucket etc.) This is like giving out to people a special type of your car key which can only turn on the music system, not the engine.
On the other hand GetOpenIdTokenForDeveloperIdentity is a special API call that needs developer credentials. You should never deploy developer credentials to any client device and you should keep it only on your server. Once you instantiate a AmazonCognitoIdentityClient using developer credentials on your server, you can expose a REST endpoint for clients to obtain OpenId token (for a given identity id or creating a new one). Let's assume that your users are logging in to your API using their username and password and you return them a custom access token which is stored in your database. After that your endpoint may implement this logic:
Fetch unique identifier for your user using custom token (user id, username, e-mail etc.)
Use LookupDeveloperIdentity and find out the identityId for the given username.
Use GetOpenIdTokenForDeveloperIdentity with found identityId and send back to the client. So they can "login" to that identityId.
If this user has not any identityId assigned to its username, create a new one and send back.
As you see developer AWS tokens are enabling a couple of sensitive API calls. Now let us assume that client had developer access token and thus has access to GetOpenIdTokenForDeveloperIdentity call. Then they would be able to generate OpenId tokens, switch to other people's identities easily and access their private data.
If you don't use developer authenticated identities (https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html) you do not need GetOpenIdTokenForDeveloperIdentity mechanism though. If you are using only public authentication methods (Twitter, Facebook etc.) you should ignore the second paragraph and use CognitoAWSCredentials.
As described in Çağatay's answer, the BasicAwsCredentials are instantiated with your developer credentials. What he described about when to use each constructor is absolutely correct in every case other than developer authenticated identities.
Since this code will be deployed on a back end service, it's exposure is less of a concern. Mobile clients will communicate with this server and get the token from it, with which they will get credentials. The credentials are never exposed to the user in this pattern.
As you can see in the Cognito documentation, the sample has BasicAwsCredentials. An end to end sample is visible in this blog post.