Gmail API Get email via Postman - postman

I'm trying to call Users.messages: get api using POSTMAN:
Request type : GET
Request : https://www.googleapis.com/gmail/v1/users/<my-email>/messages/<id>?key=<API-KEY>
Authorization : Bearer-token : <access_token received on successful login using Google>
What is the value of id?
What else is required to be added ?
Why does this return this error?
400. That’s an error. Your client has issued a malformed or illegal request. That’s all we know.

The 400 error code means you are sending the request in the wrong way. I could guess it's because you are sending an id which doesn't exist, due to the fact you don't know what represents.
That id, as the docs says, represents:
The ID of the message to retrieve.
One easy way to retrieve the messages' id, it's using the Users.messages: list endpoint and then you can try to retrieve that specific message using the Try this API tool.

Related

oAuth JWT resulting in Invalid Argument Error (400)

I'm trying to enable account linking on my google action using oAuth2 code grant flow.
Unfortunately my linking fails in the last step. I think that I'm not returning the result of my /token endpoint correctly back to google.
I can see this response of a 400 error in my console after getting redirect to my actions page (/authorize worked fine):
Request URL: https://oauthintegrations.clients6.google.com/v1/token:getForService?key=api-key-removed-by-me&alt=json
{
"error": {
"code": 400,
"message": "\u003ceye3 title='/OpenIdConsumerService.ValidateOpenId, INVALID_ARGUMENT'/\u003e APPLICATION_ERROR;apps_auth/OpenIdConsumerService.ValidateOpenId;com.google.identity.accountlinking.error.FederatedProtocolException: \u003ceye3 title='INVALID_ARGUMENT'/\u003e OpenAuth::INPUT_ERROR: ;AppErrorCode=13;StartTimeMs=1602166359350;tcp;Deadline(sec)=59.962523136;ResFormat=UNCOMPRESSED;Originator=traffic-prod;Tag=\u0002cloud_project_number\u0003744920882961\u0002IncomingMethod\u0003/OAuthIntegrationsService.GetTokenForService\u0002cidc\u00032;ServerTimeSec=1.00669508;LogBytes=256;Non-FailFast;EffSecLevel=privacy_and_integrity;ReqFormat=UNCOMPRESSED;ReqID=2d3a46fa4ab8370e;GlobalID=c34268105821e185;Server=[2002:ab3:7310::]:4155",
"status": "INVALID_ARGUMENT"
}
}
This is the body I send back to google for /token (I guess this results in the error above):
{
"access_token":"jwt-token-here",
"expires_in":"1602162256000",
"refresh_token":"refresh-token-here",
"refresh_token_expires_in":"31535999",
"token_type":"Bearer",
"scope":"read"
}
Is the structure of the body correct? I think it's because of the jwt-token but when I decode it manualy everything looks fine.
Any help appreciated!
Thank you
Unfortunately my linking fails in the last step. I think that I'm not returning the result of my /token endpoint correctly back to google.
Just a quick note that your access/refresh tokens are opaque to Google. You are handing over these credentials for Google to pass back to you in future requests. What these tokens mean, and how they are determined to be valid, is up to your OAuth server implementation.
See the OAuth account linking guide for more details.
This is the body I send back to google for /token
The fields scope and refresh_token_expires_in are not parameters Google expects in your token exchange responses, so this is likely where the INVALID_ARGUMENT error is coming from. A basic token response to Google should looking something like this:
{
"access_token":"jwt-token-here",
"expires_in":"1602162256000",
"token_type":"Bearer",
}
The expires_in field refers to the access token and when Google should use the refresh token to request a new access token.
If you want to expire or rotate your refresh tokens, you can do that as well. However, you can't tell Google when a refresh token will "expire". To rotate refresh tokens, you have to pass back the new token the next time Google requests a new access token, such as:
{
"access_token":"jwt-token-here",
"expires_in":"1602162256000",
"refresh_token":"updated-refresh-token-here",
"token_type":"Bearer",
}
See the OAuth implementation guide for more details on the fields in the requests and responses.

Alexa Request Customer contact Access Denied

I am observing a very weird behavior in Requesting Customer Contact information, email in my skill's case.
I have implemented the exact same way as mentioned in the documentation. I have provided the permission in the skill's permission tab (for email). I have granted the permission in the app and from the code, I am calling the following REST API for fetching email id of the user by passing Bearer token (consent token in permissions object received in JSON input)
https://api.eu.amazonalexa.com/v2/accounts/~current/settings/Profile.email
But the weird thing is, that recently, I am getting this response
{'code': 'ACCESS_DENIED', 'message': 'Authentication failure with
reason: TOKEN_INVALID'}
I have been recently facing this issue that sometimes the API is working fine but sometimes, it is not and I am receiving the above errors.
Can anyone help please?
I am calling the following REST API for fetching email id of the user
by passing Bearer token (consent token in permissions object received
in JSON input)
According to this doc, consentToken has been deprecated, you should use apiAccessToken instead.
Important: Requests from Alexa may also include a consentToken within
session.user.permissions and context.System.user.permissions. This
property is deprecated. Existing skills that use consentToken continue
to work, but the context.System.apiAccessToken property should be used
instead.
Thus, accessToken = this.event.context.System.apiAccessToken.
Also, double-check your header: {"Authorization": "Bearer " + apiAccessToken}, make sure you have a space between Bearer and apiAccessToken.

How to send mail using gmail rest api from postmnan native application

My requirement is that send an email to some recipient with text body using POSTMAN Native app,
I used the below endpoint with requested data,
Base URL: https://www.googleapis.com/gmail/v1/users/userId/messages/send
Headers :Authorization:Bearer
Request Method :POST
Request body :{"raw";"to:user1mail#gmail.com","subject":"Test_Mail"}
Clicking Send button
But getting error response code 400,required recipient address
Please help me in this to send an email using POSTMAN,and I've tried with upload end point too -https://www.googleapis.com/upload/gmail/v1/users/user1email#gmail.com/messages/send
Thanks in advance,looking for help guys
Came across your question trying to figure this out myself today.
Request body : {"raw";"to:user1mail#gmail.com","subject":"Test_Mail"}
The raw param should be a complete email message that's base64-encoded.
i.e.: {"raw": "VG86IHVzZXIxbWFpbEBnbWFpbC5jb20KU3ViamVjdDogVGVzdF9NYWls"}
400 error means bad request, which could mean there are missing or wrong parameters. Check the Users.messages.send
Path parameters
userId string The user's email address. The special value me can be
used to indicate the authenticated user.
Required query parameters
uploadType string The type of upload request to the /upload URI.
Acceptable values are:
media - Simple upload. Upload the media only, without any metadata.
multipart - Multipart upload. Upload both the media and its metadata, in a single request.
resumable - Resumable upload. Upload the file in a resumable fashion, using a series of at least two requests where the first
request includes the metadata.

"Provided Authorization Grant is invalid" when using refresh_token WSO2 IS 5.2.0

I recently updated my environment from WSO2 IS 5.0.0 to WSO2 IS 5.2.0. My environment consists of one machine deployed on EC2 AWS instance. I am using MySQL(not the default H2 database). The machine on which the IS is deployed is Windows Server 2012 R2.
I am using the password grant type in order to get access token for particular user and also store the refresh token so that I am able to issue another access token when needed. I am doing the following request in order to get access token:
POST
https://(IS-URL)/oauth2/token?scope=openif&grant_type=password&username=test#abv.bg#localhost.io&password=Asd123##
Configure the appropriate Authorization Basic header
After that I am using the refresh token in order to issue new access tokens. For example:
POST
https://(IS-URL)/oauth2/token?scope=openid&grant_type=refresh_token&refresh_token=
Configure the appropriate Authorization Basic header
After I execute the latest POST call from Postman several times in 2-5 sec interval, after the first 5-7 calls, I start to receive the following error response:
{
"error": "invalid_grant",
"error_description": "Provided Authorization Grant is invalid"
}
I am expecting to receive the new access token and instead I am receiving the mentioned above error. Then I modifiedthe log4j.properties by updating the following lines:
log4j.logger.org.wso2.carbon.identity=DEBUG
log4j.logger.org.wso2.carbon.identity.application=DEBUG
log4j.logger.org.wso2.carbon.identity.mgt=DEBUG
log4j.logger.org.wso2.carbon.identity.oauth2=DEBUG
log4j.logger.org.wso2.carbon.identity.provisioning=DEBUG
log4j.logger.org.wso2.carbon.identity.user.account.association=DEBUG
log4j.logger.org.wso2.carbon.identity.user.profile.mgt=DEBUG
Then I started the IS and tried again the mentioned above scenario and this is what I received in the log file:
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.OAuth2Service} - Access Token request received for Client ID GCFfyPSGkykWG4zQTKoDp8NEvjIa, User ID null, Scope : [openid] and Grant Type : refresh_token
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.clientauth.AbstractClientAuthHandler} - Can authenticate with client ID and Secret. Client ID: GCFfyPSGkykWG4zQTKoDp8NEvjIa
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.clientauth.AbstractClientAuthHandler} - Grant type : refresh_token Strict client validation set to : null
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Client credentials were available in the cache for client id : GCFfyPSGkykWG4zQTKoDp8NEvjIa
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Successfully authenticated the client with client id : GCFfyPSGkykWG4zQTKoDp8NEvjIa
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler} - Access Token is not in 'ACTIVE' or 'EXPIRED' state for Client with Client Id : GCFfyPSGkykWG4zQTKoDp8NEvjIa
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - Invalid Grant provided by the client Id: GCFfyPSGkykWG4zQTKoDp8NEvjIa
[2016-11-15 21:29:18,873] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - OAuth-Error-Code=invalid_grant client-id=GCFfyPSGkykWG4zQTKoDp8NEvjIa grant-type=refresh_token scope=openid
For more information, please take a look at the whole log file:
https://www.dropbox.com/s/ygfc9hrrgxjkzkh/console.log?dl=0
Has someone experienced similar issue and could this be bug in the IS or it is caused by some sort of misconfiguration?
I took a look at Refresh token returns invalid grant type but was not able to find direct answer to the question.
Just want to mention that I tried issuing one request per second and tried this for 5 min interval and was not able to reproduce the issue. It seems it happens when the request frequency is high enough.
Thanks in advance.
As per this code and your logs, the access token is neither in 'ACTIVE' nor 'EXPIRED' state. You can look for that particular token in IDN_OAUTH2_ACCESS_TOKEN table. That will give you a hint about what has gone wrong.
Update:
I analyzed your dataset. The problem is that since you have sent the same token request several times, there are many entries in this tables with TOKEN_STATE=INACTIVE. And also you have 2 entries with the same timestamp (i.e. 2016-11-17 11:40:02) in TIME_CREATED column, which has happened to be the latest among all. So when IS tries to pick the latest token (which ideally should be the ACTIVE one) db server returns 2 tokens. But IS has to pick just one. It can be any of those 2 since the timestamp is the same. So when it picks the INACTIVE one, you should see above error.
Ideally, IS should have handled this properly. But as a solution for you, if you do not keep sending the same request very frequently, you should be able to get rid of the error. Just send a request and wait till the response comes. If it takes a lot of time, that's a different issue to analyze and solve.

Response code 400 or 403 for POST Restful APIs

I am designing a POST Restful API, where I have a situation that I have to authorize a user based upon one of the element provided in the request body.
For eg.
{
division : "1",
name : "MyName",
address:{
no : 123,
street : "abc",
pincode : 222111
}
....
}
So the user making POST request should be authorized to work on division 1. I cannot authorize the user without getting request body.
Also to validate some of the attributes I have to make heavy DB calls in the DB , for eg, to check the above address has a valid value of pincode.
So My question is how should I return the error codes to the user -
[EDIT]If division is not valid(something that doesnt exist in system) in the request - 400 or 403 ?
If division is provided, but user is not authorized and pincode is invalid - 400 for invalid pincode or 403 ?
What should be the error code if pincode is mandatory attribute and is not provided in the request. Should I first check 403 and then 400 or reverse ?
Basically which error code to proceed the other ?
Also is it okay to do something like :
400 – request is bad, syntactically (division/pincode or other mandatory values not provided)
403 – authorize user
400 – request is bad, data specific validation (heavier operation, requiring to hit DB)
[EDIT] we preferred not to use 422 error code
When in doubt, just take a look at the RFC
400 Bad Request
The request could not be understood by the server due to malformed
syntax. The client SHOULD NOT repeat the request without
modifications.
403 Forbidden
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated. If
the request method was not HEAD and the server wishes to make public
why the request has not been fulfilled, it SHOULD describe the reason
for the refusal in the entity. If the server does not wish to make
this information available to the client, the status code 404 (Not
Found) can be used instead.
If division is not provided in the request - 400 or 403?
I don't think either apply. The syntax -although it's missing some data- is not malformed.
Also 403 seems incorrect because of reasons mentioned above in the quote: authorization will not help etc.
How about 422 Unprocessable Entity?
422 Unprocessable Entity (WebDAV; RFC 4918)
The request was well-formed but was unable to be followed due to
semantic errors.
That is what I usually use in situations like this.
If division is provided, but user is not authorized and pincode is invalid - 400 for invalid pincode or 403?
Again, I don't think either 400 or 403 make a good case here. Specifically for this situation, 401 exists
401 Unauthorized
Similar to 403 Forbidden, but specifically for use when authentication
is required and has failed or has not yet been provided. The response
must include a WWW-Authenticate header field containing a challenge
applicable to the requested resource. See Basic access authentication
and Digest access authentication.
I think you're in the right track. Assuming that every request is being authenticated via (http authorization header)
Returning 400, on missing data is OK, and furthermore you can add error response body explaining what was the reason for the Client request not being accepted (in this case the missing division).
Returning 403, is OK if the client making the request is not authorized to interact with the resource (in this case the division).
You must validate first if the Client is authorized to interact with the resource, so 403 must be sent first, and if a required field is missing you can treat it as a 400 (with a proper explanation).
In case the Client is not authenticated, the correct response should be 401, but like I said before, 1) and 2) in my response are assuming that the Clients are authenticated against the server.
Hope it helps,
Jose Luis