I have updated my user pool token expiry, however its not getting updated. Is there anything thats not correct in this config?
"userpoolClientRefreshTokenValidity": 30,
"userpoolClientIdTokenValidity": 30,
"userPoolClientTokenValidityUnits": {
"RefreshToken": "hours",
"IdToken": "hours"
},
Related
We allow our users to upload data to a S3 bucket, which then triggers a Python lambda which again updates a DynamoDB entry based on the uploaded file. In the lambda, we struggle to get the username of the user who put the item. Since the Lambda is triggered by the put event from the S3 storage, we don't have the authorizer information available in the request context. The username is required as it needs to be part of the database record.
Here some more background: Every user should only have access to her own files, so we use this IAM policy (created with CDK):
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [
bucket.arnForObjects(
'private/${cognito-identity.amazonaws.com:sub}/*'
),
],
})
Since the IAM policy validates the cognito-identity.amazonaws.com:sub field (which translates to the identity ID) we should be able to trust this value. This is the Python lambda and an example of a record we receive:
import json
import boto3
'''
{
"Records": [
{
"eventVersion": "2.1",
"eventSource": "aws:s3",
"awsRegion": "my-region-1",
"eventTime": "2023-02-13T19:50:56.886Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "AWS:XXXX:CognitoIdentityCredentials"
},
"requestParameters": {
"sourceIPAddress": "XXX"
},
"responseElements": {
"x-amz-request-id": "XXX",
"x-amz-id-2": "XX"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "XXX",
"bucket": {
"name": "XXX",
"ownerIdentity": {
"principalId": "XXX"
},
"arn": "arn:aws:s3:::XXX"
},
"object": {
"key": "private/my-region-1%00000000-0000-0000-0000-000000000/my-file",
"size": 123,
"eTag": "XXX",
"sequencer": "XXX"
}
}
}
]
}
'''
print('Loading function')
dynamodb = boto3.client('dynamodb')
cognito = boto3.client('cognito-idp')
cognito_id = boto3.client('cognito-identity')
print("Created clients")
def handler(event, context):
# context.identity returns None
print("Received event: " + json.dumps(event, indent=2))
for record in event['Records']:
time = record['eventTime']
key = record['s3']['object']['key']
identityId = key.split('/')[1]
# How to get the username from the identityId?
return "Done"
Things we tried:
Try to find an alternative to cognito-identity.amazonaws.com:sub which validates the username, but from the documentation there is no option for that
Encode the username in the bucket key, but this opens a security hole as then a client can pretend to have a different username
Make a lookup with https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-identity.html to find the username for an identity ID, but so far we haven't found anything there
Tried to follow How to get user attributes (username, email, etc.) using cognito identity id, but in the Lambda we don't have an ID or access token available
Getting cognito user pool username from cognito identity pool identityId, but since the Lambda is triggered by a S3 put event, we don't have an authorizer context
We could store the identity ID as custom attribute of every Cognito user (as suggested here How to map Cognito (federated) identity ID to Cognito user pool ID?), but before I do that I would like to be sure that there isn't a better option as I fear that the duplication of this information could lead to issues in the long run.
I am implementing Vault for my team to use and store secrets, and we wanted to keep it simple so we decided to go with the default token authentication.
The thing is I can't find a way to manage tokens that were created, so that if I want to revoke a certain person's token, I know exactly which one to revoke.
Does anyone know how to manage tokens in Vault?
You cannot list the tokens because tokens are sensitive information.
You can list token accessors (API docs)
which will give you a value like this 476ea048-ded5-4d07-eeea-938c6b4e43ec which is safe to share - think of it as a pointer to the token.
Then you can lookup the token accessor (API docs) and get a response like this
{
"data": {
"accessor": "8609694a-cdbc-db9b-d345-e782dbb562ed",
"creation_time": 1523979354,
"creation_ttl": 2764800,
"display_name": "ldap2-tesla",
"entity_id": "7d2e3179-f69b-450c-7179-ac8ee8bd8ca9",
"expire_time": "2018-05-19T11:35:54.466476215-04:00",
"explicit_max_ttl": 0,
"id": "",
"identity_policies": ["dev-group-policy"],
"issue_time": "2018-04-17T11:35:54.466476078-04:00",
"meta": {
"username": "tesla"
},
"num_uses": 0,
"orphan": true,
"path": "auth/ldap2/login/tesla",
"policies": ["default", "testgroup2-policy"],
"renewable": true,
"ttl": 2763902
}
}
which will probably help you figure out if the tokens requires revoking or not.
Been at this for a few days. I am making a login form on my angular/nodejs app. The bc-api is able to verify the user/password. Now with that i need to allow the customer to enter the store with sso but the generated jwt is not working. My attempt below... I am looking for troubleshooting tips.
Generate JWT / sso_url
var jwt = require('jwt-simple');
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
function get_token(req, data) {
let uid = req.id;
let time = Math.round((new Date()).getTime() / 1000);
let payload = {
"iss": app.clientId,
// "iat": Math.floor(new Date() / 1000),
"iat": time,
"jti": uid+"-"+time,
"operation": "customer_login",
"store_hash": app.storeHash,
"customer_id": uid,
"redirect_to": app.entry_url
}
let token = jwt.encode(payload, app.secret, 'HS512');
token = decode_utf8(token);
let sso_url = {sso_url: `${app.entry_url}/login/token/${token}`}
return sso_url
}
payload resolves to
{
"iss": "hm6ntr11uikz****l3j2o662eurac9w",
"iat": 1529512418,
"jti": "1-1529512418",
"operation": "customer_login",
"store_hash": "2bihpr2wvz",
"customer_id": "1",
"redirect_to": "https://store-2bihpr2wvz.mybigcommerce.com"
}
generated sso_url
https://store-2bihpr2wvz.mybigcommerce.com/login/token/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJobTZudHIxMXVpa3oxMXpkbDNqMm82NjJldXJhYzl3IiwiaWF0IjoxNTI5NTEyNDE4LCJqdGkiOiIxLTE1Mjk1MTI0MTgiLCJvcGVyYXRpb24iOiJjdXN0b21lcl9sb2dpbiIsInN0b3JlX2hhc2giOiIyYmlocHIyd3Z6IiwiY3VzdG9tZXJfaWQiOiIxIiwicmVkaXJlY3RfdG8iOiJodHRwczovL3N0b3JlLTJiaWhwcjJ3dnoubXliaWdjb21tZXJjZS5jb20ifQ.vaeVTw4NjvX6AAPChgdXgMhm9b1W5B2QEwi4sJ6jz9KsKalqTqleijjRKs8jZP8jdQxC4ofYX5W0wYPMTquxQQ
result
about my env
I am using nodejs express... my bc app's secret & clientId are being used above and they work for several other bc-api tasks. My app is installed and authenticated on bc admin. The app being used to do the above is running on localhost but i also tried online https (same result).
I am thinking that there might be some incorrect configuration in my stores admin but havent found anything to change.
I decoded your JWT on jwt.io and I get this:
Header:
{
"typ": "JWT",
"alg": "HS512"
}
There's at least one problem here
BC requires HS256 as the algorithm according to docs
https://developer.bigcommerce.com/api/v3/storefront.html#/introduction/customer-login-api
Body:
{
"iss": "hm6ntr11uikz11zdl3j2o662eurac9w",
"iat": 1529512418,
"jti": "1-1529512418",
"operation": "customer_login",
"store_hash": "2bihpr2wvz",
"customer_id": "1",
"redirect_to": "https://store-2bihpr2wvz.mybigcommerce.com"
}
Problems here:
JTI should be a totally random string, using something containing the time could result in duplicates which will be rejected. Try using a UUID
Customer ID should be an int, not a string
The redirect_to parameter accepts relative URLs only. So try "redirect_to": "/" if your goal is to redirect to the home page.
Another potential problem is system time - if your JWT was created in the "future" according to BC's server time, your JWT also won't work. You can use the /v2/time endpoint response to specify the IAT, or to keep your own clock in sync.
I am trying to verify various MFA based accounts Yodlee API by performing following steps:
Successful call to addSiteAccount1
In response, it does return siteAccountId
In response, it also provides site refresh status that REFRESH_TRIGGERED
if resp['siteRefreshInfo']['siteRefreshMode']['refreshMode'] == 'MFA' and
resp['siteRefreshInfo']['isMFAInputRequired'] == True and
resp['siteRefreshInfo']['siteRefreshStatus']['siteRefreshStatus'] ==
'REFRESH_TRIGGERED'
Now, calling getMFAResponseForSite repeatedly together with getSiteRefreshInfo results into initially code 801 and than 508 eventually timeout.
Eventually, I come out of the loop with result isMessageAvailable: True
{u'itemId': 0,
u'retry': False, u'timeOutTime': 99880, u'memSiteAccId': 10144098,
u'errorCode': 0, u'isMessageAvailable': True, u'fieldInfo':
{u'questionAndAnswerValues': [], u'numOfMandatoryQuestions': -1,
u'mfaFieldInfoType': u'SECURITY_QUESTION'}}
The only concern I have is that it provides mfaFieldInfoType, but it doesn't provide the actual question.
Couple questions:
a. How do I retrieve proper MFA question(s) for the site?
b. If user is initially coming into system and would like to link account more than couple second wait for user will kill the experience - so what's the recommended time period to be allowed to get MFA question?
c. Is this due to development vs. production environment difference?
d. I can retrieve account and holdings details for account, however than the account results in NON_REFRESHABLE state.
After calling addSiteAccount1 API, you get siteAccountId for an account.
Pass the siteAccountId to getMFAResponseForSite API and keep polling until you get the MFA form. then pass the MFA form with valid values to putMFARequestForSite API.
Please refer to our API flow- https://developer.yodlee.com/Aggregation_API/Aggregation_Services_Guide/API_Flow/Add_Site_Account
Blockquote
Sample response-
{ "isMessageAvailable": true, "fieldInfo": {
"questionAndAnswerValues": [
{
"question": "What is the name of your state?",
"questionFieldType": "label",
"responseFieldType": "text",
"isRequired": "true",
"sequence": 1,
"metaData": "QUESTION_1"
},
{
"question": "What is the name of your first school",
"questionFieldType": "label",
"responseFieldType": "text",
"isRequired": "true",
"sequence": 2,
"metaData": "QUESTION_2"
}
],
"numOfMandatoryQuestions": 2,
"mfaFieldInfoType": "SECURITY_QUESTION" }, "timeOutTime": 97340, "itemId": 0, "memSiteAccId": 10003775, "retry": false }
I can request a token for a user by visiting the following url:
https://trello.com/1/connect?key=<key>&name=appName&response_type=token&scope=read,write&expiration=never
However, when I request the token's info through the API, I get a response that looks like this:
{
"id": "...",
"identifier": "appName",
"idMember": "...",
"dateCreated": "2015-10-15T05:21:19.886Z",
"dateExpires": null,
"permissions": [
{
"idModel": "*",
"modelType": "Board",
"read": true,
"write": true
},
{
"idModel": "*",
"modelType": "Organization",
"read": true,
"write": true
}
]
}
I'd like to be able to request a token only grant privileges to a specific organization. But I can't seem to find clear documentation on what kinds of options the /1/connect endpoint accepts, or what other method I can use to obtain a token for a specific organization that does not expire.
I could make a machine user with access only to the organization, but it would be a shame to pay for another user account when I only want a subset of the permissions I already have.
I don't think that would be possible as you just authenticate against the API as that user and therefore have the ability to see everything that user can. The only way I'm aware of would be (as you suggested) to create a new user and limit what they can see.