Plaid - Update mode not working showing ITEM_LOGIN_REQUIRED - plaid

I am new to plaid.
I created a plaid access_token and now its showing
"error_code":"ITEM_LOGIN_REQUIRED"
Using the doc I understand that we need to use update mode for solving this
then access token will not change and no need to call token -exchange
after getting this error
I tried calling
https://sandbox.plaid.com/link/token/create
method -POST
{
"client_id": "xxxxxx",
"secret": "xxxxxx",
"client_name": "test",
"user": { "client_user_id": "xxxx" },
"country_codes": ["US"],
"language": "en",
"access_token": "access-sandbox-xxxx-xxx-xxx-xxx-111111"
}
then I got new link_token
{
"expiration": "2021-11-09T13:46:12Z",
"link_token": "link-sandbox-xxxx-xxx-xxxx-xxx-xxx",
"request_id": "xxxxx"
}
Then after what I need to do ?? .. I understand that no need to do token exchange api.
but if I tried to use this api using the existing access-token it is showing the same error
https://sandbox.plaid.com/accounts/get
method -POST
{
"client_id": "xxxxxx",
"secret": "xxxxxx",
"access_token": "access-sandbox-xxxx-xxx-xxx-xxx-111111"
}
output
{
"display_message": null,
"error_code": "ITEM_LOGIN_REQUIRED",
"error_message": "the login details of this item have changed (credentials, MFA, or required user action) and a user login is required to update this information. use Link's update mode to restore the item to a good state",
"error_type": "ITEM_ERROR",
"request_id": "3LMjpQHxYAMDwos",
"suggested_action": null
}
in that document they are saying like this.
An Item's access_token does not change when using Link in update mode, so there is no need to repeat the exchange token process.
then why I am getting again this ??
What I need to do solve this issue?
// Initialize Link with the token parameter
// set to the generated link_token for the Item
const linkHandler = Plaid.create({
token: 'GENERATED_LINK_TOKEN',
onSuccess: (public_token, metadata) => {
// You do not need to repeat the /item/public_token/exchange
// process when a user uses Link in update mode.
// The Item's access_token has not changed.
},
onExit: (err, metadata) => {
// The user exited the Link flow.
if (err != null) {
// The user encountered a Plaid API error prior
// to exiting.
}
// metadata contains the most recent API request ID and the
// Link session ID. Storing this information is helpful
// for support.
},
});

After getting the Link token, you need to initialize Link with the Link token. Per the docs:
"To use update mode for an Item, initialize Link with a link_token configured with the access_token for the Item that you wish to update."
https://plaid.com/docs/link/update-mode/
Once the user has successfully completed the Link flow, the access token should be reactivated.

Related

Blazor WebApi Identity Information

I am having trouble getting the users Identity information from within the API.
My project consists of a standalone WASM app, IDP and WebApi.
I have everything setup and it works but what I am after is a Call from the Blazor client to get some data from the api. The Api then uses the users email address to identify them and get the data just for them.
I have looked at similar questions and the solutions don't work for me on my project.
[HttpGet("GetData")]
public async Task<IActionResult> GetData()
{
string test = User.Identity.Name; // returns null
string username = "myuser#users.com";
List<string> data= new List<string>();
data= (await _dataRepository.GetData(username)).ToList();
if (data.Count > 0)
{
return Ok(data);
}
else
{
return NoContent();
}
}
So where I am setting the username is there a way to get a hold of the email of the user who passed the request?
Edited
Access Token:
{
"alg": "RS256",
"kid": "2D49329C75FC43C78590AF6F6A0EFDB2",
"typ": "at+jwt"
}
{
"nbf": 1639243158,
"exp": 1639246758,
"iss": "https://localhost:5000",
"aud": "https://localhost:5000/resources",
"client_id": "ATS",
"sub": "4892725f-f6da-4a28-827a-ce666bb6f098",
"auth_time": 1638729064,
"idp": "local",
"jti": "53CB2F8FCB2EB34E3501E2C210B59B5D",
"sid": "8463E4AA74D7369C1176249ED8FA46B1",
"iat": 1639243158,
"scope": [
"openid",
"profile",
"MY_API"
"email"
],
"amr": [
"pwd"
]
}
First you would typically secure your controller action methods using the [Authorize(...)] attribute and lookup the authorization in ASP.NET Core for more details about that.
Second, the most common problem when the name/email is not found is that you need to turn of the claims mapping using
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
This is because by default Microsoft and OpenID have different opinions on what the claim names should be and because of that it can be wise to first clear this mapping and then secondly, point tell Microsoft what the name of the name/role claim by setting this:
opt.TokenValidationParameters.RoleClaimType = "roles";
opt.TokenValidationParameters.NameClaimType = "name";
For more details about claims mapping visit:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0

Google Drive api Permission value field required

I am writing an angular code to give permission to another account to access a particular file in google drive.
public async givepremission(fileid,email){
await gapi.client.setApiKey(this.credconst.APIkey.toString());
return await gapi.client.load("drive","v3")
.then(async () =>
{
return await gapi.client.drive.permissions.create({
"fileId": fileid,
"resource": {
"role": "reader",
"type": "user",
"emailAddress": email
}
}) },
(err) => {
this.toastr.error('Google API error');
throw(err);
});
}
But all i am getting is an error
domain: "global"
reason: "required"
message: "Permission value field required"
locationType: "other"
location: "permission.value"
I tried it in the https://developers.google.com/drive/api/v3/reference/permissions/create Try This API there it is working fine but in my project it throws the above error.
The account I am using to give permission is not a G-Suite user.
I have no idea why this error pops up?
How can I solve this issue?
-Thanks
if you have a look here https://developers.google.com/drive/api/v2/reference/permissions/insert
under "Optional Properties" you have the value field
here's the requestBody you should pass:
requestBody:{
emailAddress:'fabrizio#keyko.io',
role:'writer',
type:'user',
value: 'fabrizio#keyko.io'
},
I had the same error but now it works for me.

How to pass the validation code to the Lambda function

I'm trying to customize the email that AWS Cognito sends if a user has forgotten their password.
It requires {####} placeholder for the verification code in the email message. For example, if you do
event['response']['emailMessage'] = "Your code is {####}", you'll receive a message Your code is 123456.
Here's an example of my AWS Lambda function:
def custom_message_handler(event, context):
event['response']['emailSubject'] = 'Custom subject'
event['response']['emailMessage'] = 'Custom email'
# verification_code = event[...] ???
return event
It seems like Cognito generates the verification code after your lambda returned the message with the placeholder. Is it possible to get the verification code inside your lambda to use it?
Amazon Cognito's Custom Message Lambda Trigger's Event JSON does not get the numerical verification code. The data of the Event available to the trigger, as stated in the official documentation is stated as follows:
{
"version": 1,
"triggerSource": "CustomMessage_AdminCreateUser",
"region": "<region>",
"userPoolId": "<userPoolId>",
"userName": "<userName>",
"callerContext": {
"awsSdk": "<calling aws sdk with version>",
"clientId": "<apps client id>",
...
},
"request": {
"userAttributes": {
"phone_number_verified": false,
"email_verified": true,
...
},
"codeParameter": "####",
"usernameParameter": "username"
},
"response": {
"smsMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailMessage": "<custom message to be sent in the message with code parameter and username parameter>"
"emailSubject": "<custom email subject>"
}
}
You would be able to use Cognito data in a Lambda trigger only if it is available in an Event, or if there is a separate API call for the same. But given Amazon Cognito's design, this does not seem to be possible.

Getting Daily Limit for unauthenticated use Exceeded

Getting Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup
when executing the following code given in the Xamarin demo
async void OnAuthenticationCompleted (object sender, AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated) {
// If the user is authenticated, request their basic user data from Google
// UserInfoUrl = https://www.googleapis.com/oauth2/v2/userinfo
var request = new OAuth2Request ("GET", new Uri (Constants.UserInfoUrl), null, e.Account);
var response = await request.GetResponseAsync ();
if (response != null) {
// Deserialize the data and store it in the account store
// The users email address will be used to identify data in SimpleDB
string userJson = response.GetResponseText ();
App.User = JsonConvert.DeserializeObject<User> (userJson);
e.Account.Username = App.User.Email;
AccountStore.Create ().Save (e.Account, App.AppName);
}
}
// If the user is logged in navigate to the TodoList page.
// Otherwise allow another login attempt.
App.SuccessfulLoginAction.Invoke ();
}
This is the error I am getting
"error":{
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message" :"Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
"extendedHelp" : "https://code.google/apis/console"
}
],
"code":403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
I corrected the redireturl to "http://example.com/oauth2callback" and in the ios project modified the ATS setting by adding the following key in info.plist
NSAppTransportSecurity -- Dictionary
NSAllowsArbitraryLoadsInWebContent -- Boolean -- Yes

Can't write acl rules to primary calendar in google service account

So I have set up a google service account for one of my apps. My intention is to keep a google calendar associated with the admin portal that all of the admins can post events to. I have got the JWT auth working I can post events to the calendar and perform other API actions. However, for some reason I cannot change the access control rules on the primary calendar. It is initialized with a single acl rule (role: owner, scope: {type: user, value: service_account_id}), and when I try to add public read access (role: reader, scope: {type: default}) like so:
POST https://www.googleapis.com/calendar/v3/calendars/primary/acl
Authorization: Bearer my_jwt_here
{
"role":"reader",
"scope":{
"type":"default"
}
}
I get the following error:
{
"error": {
"errors": [
{
"domain": "calendar",
"reason": "cannotRemoveLastCalendarOwnerFromAcl",
"message": "Cannot remove the last owner of a calendar from the access control list."
}
],
"code": 403,
"message": "Cannot remove the last owner of a calendar from the access control list."
}
}
This doesn't make any sense to me because this request shouldn't be trying to remove any access control rules. When I create a secondary calendar and do this I have no issues. When I do this with the primary calendar of my personal google account I have no issues. Is this some behavior specific to service accounts that I am not familiar with or what? I could settle for using a non-primary calendar but it bothers me that this isn't working. Any advice is appreciated.
so I found a weird work around for this issue and im posting here because I could not find SQUAT to help resolve this so hopefully this saves others some hassle.
I will also post some common problems I found when creating a organization-wide calendar (whether this is your use case or not I believe these tips will be helpful) - Jump to the bottom of the solution to this particular error.
First I needed to set up authentication with google calendar:
const { google } = require("googleapis");
const calendar = google.calendar("v3");
const scopes = [
"https://www.googleapis.com/auth/admin.directory.resource.calendar",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/admin.directory.user",
];
const path = require("path");
const key = require(path.join(__dirname, "google-cal-api.json"));
I created a service account and then allowed it domain wide delegation with the above listed scopes; then downloaded the key. Now if you want to do actions like create calendar events FOR users within this domain what you have to do is generate a JWT token that 'impersonates' the user whos calendar you wish to interact with; like so
const generateInpersonationKey = (email) => {
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
scopes,
email
);
return jwtClient;
};
To set up a JWT client for the service account itself (and so you can create a calendar people can subscribe to; in our case it was a google calendar to show whos on leave within the workplace; so a calendar that has ALL that people can subscribe and toggle on/off was ideal) you just replace the email with 'null' and it defaults to itself, instead of 'impersonating' someone within the domain wide org.
Creating events are simple, follow the google cal api docs, depending on the auth token will depend on where the calendar is generated
JUMP HERE FOR THE IMMEDIATE SOLUTION TO THE ABOVE
For resolving the issue you pointed out; What I did was set my personal accounts email as an owner of this service accounts calendar with the following NodeJS code:
var request = await calendar.acl.insert({
auth,
calendarId: "primary",
resource: {
role: "owner",
scope: {
type: "user",
value: "callum#orgdomain.com",
},
},
});
I set myself as an owner, then I went to Google Calendar API > Patch (Try Me) filled in the calendarId as the service account with the calendar im trying to restrict; and then rule ID would be the gsuite domain domain:orgdomain.com The body should be
{
"role": "reader",
"scope": {
"type": "domain",
"value": "orgdomain.com"
}
}
And thats how I was able to restrict people within our gsuite domain from deleting or editing custom calendar events. This solution is coming from the perspective of someone who originally inserted the domain ACL as
var request = await calendar.acl.insert({
auth,
calendarId: "primary",
resource: {
role: "owner",
scope: { type: "domain", value: "orgdomain.com" },
},
});
Because adding it as a 'reader' like this messes with the service account ownership and wont allow anything but owner
Hope this has been helpful
Callum

Resources