SendGrid: Error when trying to add scopes with the API - api

I'm trying to add scopes to an API key with the API (actually to the same key I'm using to connect to the API).
I'm following the example in the doc, and my current scopes do include the api_key_update permission.
However when I try to add more scopes to the API key, I always receive a 400 Bad Request error.
For example apparently this is the bare minimum of scopes when having set the "API Keys" permission to "Full Access" in the admin panel (retrieved via the GET v3/scopes API endpoint):
templates.read
api_keys.create
api_keys.read
api_keys.update
api_keys.delete
sender_verification_eligible
2fa_required
And when I now try to add a mail.send scope to it, I receive this error message:
{"errors":[{"field":null,"message":"unauthorized scopes: [mail.send]"}]}
When I just pass the already existing scopes, I receive a successful response. I can also remove scopes successfully by leaving them out of the passed array. But I cannot add them, no matter which scope I try to add.
I've tested with Node.JS and with curl, here are the curl test scripts:
Working:
curl -X PUT --header "Authorization: Bearer INSERT_API_KEY" --header "Content-Type: application/json" --data '{"name": "INSERT_API_KEY_NAME", "scopes": ["templates.read", "api_keys.create", "api_keys.read", "api_keys.update", "api_keys.delete", "sender_verification_eligible", "2fa_required"]}' https://api.sendgrid.com/v3/api_keys/INSERT_API_KEY_ID
Not working:
curl -X PUT --header "Authorization: Bearer INSERT_API_KEY" --header "Content-Type: application/json" --data '{"name": "INSERT_API_KEY_NAME", "scopes": ["templates.read", "api_keys.create", "api_keys.read", "api_keys.update", "api_keys.delete", "sender_verification_eligible", "2fa_required", "mail.send"]}' https://api.sendgrid.com/v3/api_keys/INSERT_API_KEY_ID

I got to the bottom of this.
An API Key with permission to update other API keys can only give permissions that the API Key itself has. That's why an API key with full access was able to update the scopes on another API Key, but your API Key with only a few permissions including access to update other API keys couldn't add other scopes. This also leads to the conclusion that an API key cannot give itself further permissions too.
This makes sense for limited scope API keys. The intention behind the limits are that you can limit the potential damage from leaking an API key if it can only perform certain actions. If you leaked a key and it was able to add permissions to itself, that would render the limited permission feature useless.
We accept that this isn't clear in the documentation and we have raised an issue to update the documentation so this is more obvious.

Related

Trying to login using oauth. Can someone explain the documentation how to get access token?

I understand that I need to call:
curl --request POST \
--url 'https://auth.atlassian.com/oauth/token' \
--header 'Content-Type: application/json' \
--data '{"grant_type": "authorization_code","client_id": "YOUR_CLIENT_ID","client_secret": "YOUR_CLIENT_SECRET","code": "YOUR_AUTHORIZATION_CODE","redirect_uri": "https://YOUR_APP_CALLBACK_URL"}'
to get access token. There is some attempt to explain what are client_id, client_secret, code, redirect_uri, but it's totally cryptic to me. Can someone explain to me, what these are and where to get them?
I can login to company jira. I can create my personal access token in my profile. I cant get any meaningful support from my company. I need to get somehow from here to access token, so that I can call rest api.
OAuth needs that the user login through a web interface.
Once logged, is possible to retrieve the code you are looking for in the URL.
In my case, in order to get that code I have to open the oauth login web page of the service I want to use (in your case atlassian) and just login.
I usually manage this process with code, not using curls.
redirect_uri is where you want to be redirected after you login in the web interface.
i.e. Do I need to login with atlassian in order to call api and use data from my app ?
mobile app/Desktop App (redirect_uri will be a schema defined by you in the app, could be something like: myCompany://myApplicationExample or with desktop http://localhost should work ). In this case I suggest you to read something about deeplink for applications.
website (redirect_uri will the url of your website : https://yourwebsite.com
In my case, with the services I usually work with, cliend_id and client_secret are given per user or per application, when requested to the company which provides services you need.
I hope this can help you clarify
BY THE WAY:
if you say you already have an Access Token , you should be able to do everything without Loggin in, because the final purpose of login and use all this parameters you asked for, is to get an Access Token.
The endpoint you are trying to call, will just return you an Access Token.
The Access token is what you need in order to call rest api in this case.
I would suggest you to try to call an atlassian rest API you want, using the Access Token you already have in the headers of the rest API, and see the results.
In my case, I have to create an header like this:
Authorization : Bearer {your Access token}
I hope this helps you.
EDIT:
As shown in point 1 in this doc https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/
you should open this url by your application:
https://auth.atlassian.com/authorize?
audience=api.atlassian.com&
client_id=YOUR_CLIENT_ID&
scope=REQUESTED_SCOPE_ONE%20REQUESTED_SCOPE_TWO&
redirect_uri=https://YOUR_APP_CALLBACK_URL&
state=YOUR_USER_BOUND_VALUE&
response_type=code&
prompt=consent
read the doc on you should set redirect_uri (http://localhost is valid if is a desktop application, but you will have to implement an http listener in order to get the authorization code, I suggest you to set a schema in you app or simply use a web page url).
You should get a client_id by atlassian to use in the url,same for scope.
I don't know exaclty the state parameter but in the docs should be writtend.
Once logged you will be redirected to the redirect_uri you set, getting also this authorization_code, then you can call the /token endpoint in order to get the Access Token.
curl --request POST \
--url 'https://auth.atlassian.com/oauth/token'
--header 'Content-Type: application/json'
--data '{"grant_type": "authorization_code","client_id": "YOUR_CLIENT_ID","client_secret": "YOUR_CLIENT_SECRET","code": "YOUR_AUTHORIZATION_CODE","redirect_uri": "https://YOUR_APP_CALLBACK_URL"}'
Here you have to use the authorization code you get from the login, re use the same client_id, set also the client_secret (should be given with the client_id) and re use the same redirect_uri you used in the login url.
Once done you will have finally the Access Token, which must be used in order to call Apis.
as shown in the doc you should be able to call apis like this curl
curl --request GET \
--url https://api.atlassian.com/oauth/token/accessible-resources
--header 'Authorization: Bearer ACCESS_TOKEN'
--header 'Accept: application/json'
Where 'ACCESS_TOKEN' will be your access token obtained before.
Remind that an Access Token usually has an expiration date, after which you will need to login again or refreshing the token.
EDIT 2:
A Client ID is an identifier associated with an application that assists with client / server OAuth 2.0 authentication.
So basically is a constant string, this should be given to you from atlassian/jira in some way.
Client Secret should be given to you with Client ID from atlassian/jira.
Client_id and client_secret usually are also called api keys.
Usually the Scope is the name of the application you are requesting api keys for (you should request new api keys for each application),this is up to you, and should be comunicated to the company in your case (atlassian/jira) when requesting api keys.
(i.e. For my company I work with Trimble Connect, which is just a platform, everytime I develop for example a plugin/addon on top of it I ask them new api keys)
for what concerns the state:
state: (required for security) Set this to a value that is associated with the user you are directing to the authorization URL, for example, a hash of the user's session ID. Make sure that this is a value that cannot be guessed. You may be able to generate and validate this value automatically, if you are using an OAuth 2.0 client library or an authentication library with OAuth 2.0 support.
In the beginning I would try to give the state a random value.
I think you should ask to Atlassian how to get your api keys (maybe there's a page for that, like for Trimble Connect in my case).
I would send them an e-mail.
Seems you are not interested in call Apis from an application you are developing, but just from curls.
if I'm right, I know I have already told you, but if I were you I would definitely try to call an atlassian API not trying to get the access token from the OAuth Login, but using that ACCESS TOKEN you told me you told me you manually created.
Please try this curl:
curl --request GET \
--url https://api.atlassian.com/oauth/token/accessible-resources
--header 'Authorization: Bearer {ACCESS_TOKEN}'
--header 'Accept: application/json'
just use your Access Token string instead of {ACCESS_TOKEN} and see the results.

Soundcloud API authentication always throws "401 - Unauthorized"

Due to the new updates of the Soundcloud API, I'm trying to update the authentication flow in my code ( the project was using login and password ).
But I'm blocked by a problem, and I'm losing my head.
I follow instructions on this page : https://developers.soundcloud.com/blog/security-updates-api
I manage to get a refresh token and an access token with this :
curl --request POST \
--url https://api.soundcloud.com/oauth2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data client_id=CLIENT_ID \
--data client_secret=CLIENT_SECRET \
--data grant_type=client_credentials
But I'm not able to execute this request, which is an example in the mentionned page, with the access token I got with the previous request :
curl --request GET \
--url 'https://api.soundcloud.com/me/tracks?limit=1' \
--header 'Authorization: OAuth ACCESS_TOKEN'
The request response is always :{"code":401,"message":"","link":"https://developers.soundcloud.com/docs/api/explorer/open-api","status":"401 - Unauthorized","errors":[],"error":null}
I tried with a refresh of my access token, and with the url "https://api.soundcloud.com/me" instead of "https://api.soundcloud.com/me/tracks?limit=1".
And always returning the same error.
Can someone help me ?
Thanks by advance, and thanks for reading.
OK, I think I got it, thanks to this question on github :
https://github.com/soundcloud/api/issues/76
"The client_credentials auth flow is meant only for server-side integration and allows access to public endpoints only. Meaning that for endpoint /me or any other user-related endpoint you have to use the Authorization Code flow which provides the client-side integration."
And here : https://developers.soundcloud.com/docs/api/guide#authentication :
"if your app needs to access only public resources, you can use the OAuth Client Credentials Flow"
I'm done with the error messages too blurry... and with me reading too fast !
I will add the correct authentication method in comments later.
UPDATE : "manual" authentication flow
As the project is behind a VPN, I can't use normal authentication flow ( redirect_uri can't be called by soundcloud !)
So :
Get a "code"
First, authenticate on SoundCloud with the account you want to access ( or ask your customer to do it )
In your browser, type this url :
https://api.soundcloud.com/connect?client_id=YOUR_CLIENT_ID&response_type=code&scope=&state=[random_string]&redirect_uri=YOUR_REDIRECT_URI
Accept the demand and this will redirect you to an URL with the code inside : code=YOUR_CODE. Keep it. If this is done by your customer, simply ask him to copy-paste the url.
That's not really secure, but you can't avoid it if your redirect uri is not accessible from Soundcloud.
Obtain a refresh token and an access token :
With curl, to keep your Client Secret, or App Secret, secret ( indeed :D ). And also the access token.
curl -X POST "https://api.soundcloud.com/oauth2/token"
-H "accept: application/json; charset=utf-8"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=authorization_code&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=YOUR_REDIRECT_URI&code=YOUR_CODE"
This last request will answer in json format. Inside, you'll find an access token, and a refresh token.
Register the refresh token in your projet to reuse it to refresh your access token when needed !

Authorizing wikimedia API usage: rest-read-denied error

I'm trying to fetch a decent number of API URLs like https://api.wikimedia.org/core/v1/wikipedia/en/file/File%3AFlag%20of%20Madison%20Heights%2C%20Michigan.svg.
I have signed up for an API key as described in the instructions.
However, when I issue my requests with the Authorization: Bearer [long JWT Access Token goes here] header, I just get {"error":"rest-read-denied","httpCode":403,"httpReason":"Forbidden"} back.
If I omit the Authorization header, then I do get a good response, but am severely rate limited.
The API Portal says that my API key is approved. I have tried resetting the secret, and have tried creating a separate one, I have inspected the exact headers sent by using curl -v and I can see the Authorization header in there and it looks correct (diffed it with the access token).
If I modify the token, then I get a different error message: {"httpCode":401,"httpReason":"Jwt verification fails"} so clearly my token is passed in correctly and it's a permissions issue with my API key. I have tried both a key with read only permission, and a key with both read & edit permissions, but no dice.
The example cURL request in the signup instruction also fails with a rest-read-denied error:
curl -H "Authorization: Bearer $AccessToken" \
https://api.wikimedia.org/core/v1/wikipedia/en/page/Earth/bare
!?!?

Auth0 right way to call userinfo

I have created an API with RS256 signing algorithm and http://localhost:3000/api/v1 as the Identifier (audience) and I added openid, phone, profile as the scopes to the created API
Then created an application to invoke the above API, with RS256 signing and turned off OIDC Conformant since I'm using a customized login page.
I was able to invoke the following authorize request successfully :
https://hostname.auth0.com/authorize?client_id=CLIENT_ID&redirect_uri=http://localhost:4200/dashboard&response_type=code&scope=openid%20profile&state=state&nonce=nonce&audience=https://hostname.auth0.com/userinfo
After getting the code I was able to execute the token call and received the access_token
curl --request POST \ --url https://hostname.auth0.com/oauth/token \ --header 'content-type: application/json' \ --data '{"client_id":"CLIENT_ID","client_secret":"CLIENT_SECRET","audience":"localhost:3000/api/v1","grant_type":"client_credentials","code": "CODE"}'
But after decoding the JWT token I couldn't see the userinfo endpoint in audience field
So I'm getting unauthorized error in executing the following userinfo call, but I was able to call my other API (secured resources) using the given access token without any issue.
curl --request GET \
--url 'https://hostname.auth0.com/userinfo' \
--header 'authorization: Bearer {ACCESS_TOKEN}' \
--header 'content-type: application/json'
Unauthorized
-Then I tried to invoke the token endpoint using userinfo url as the audience value:
curl --request POST \
--url https://hostname.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"CLIENT_ID","client_secret":"CLIENT_SECRET","audience":"https://hostname.auth0.com/userinfo","grant_type":"client_credentials","code": "CODE"}'
Then I'm getting the following error:
{"error":"access_denied","error_description":"Client is not authorized to access \"https://hostname.auth0.com/userinfo\". You might probably want to create a \"client-grant\" associated to this API. See: https://auth0.com/docs/api/v2#!/Client_Grants/post_client_grants"}
When I tried to add userinfo url as an additional Identifier (audience) when creating an API, I'm getting an error saying 'provided identifier is reserved'
Please let me know what I'm doing wrong here. Looking forward to your reply.
Thanks.
I see multiple issues in what you are doing.
If you are looking to get an access token for your API as well, you should specify that API's identifier as the audience in the initial /authorize call. /userinfo audience is assumed, so you don't need to specifically mention it. For example, if your API identifier is https://api.example.com:
https://hostname.auth0.com/authorize?client_id=CLIENT_ID&redirect_uri=http://localhost:4200/dashboard&response_type=code&scope=openid%20profile&state=state&nonce=nonce&audience=https://api.example.com
You may also want to specify some of the scopes defined in the API in the above call (apart from openid and profile).
When you exchange the code to tokens, the grant_type should be authorization_code (not client_credentials). Also, you don't need to specify the audience again during this code exchange. But make sure you specify the redirect_uri that you sent in initial /authorize request here as well. This is required to prevent some attack vectors.
Changing the API calls based on the above points should send you back the correct access token - which can be used to both call your API and the /userinfo endpoint.
More info about this flow can be found in the docs: https://auth0.com/docs/api-auth/tutorials/authorization-code-grant

Authenticate to API with secret key and credentials

I am trying to make a request to the TaskRabbit API. I want to use my credentials and get the details of my account back.
I have a developer account (application ID, application Secret, Authorize URL). How can I use these credentials to authenticate with TaskRabbit? Can I use something like curl to test this out?
I tried using something like
curl -X POST -H "Content-Type: application/json" -d '{"username":"my username","password":"my password"}' https://combo-staging-2.taskrabbit.in/api/v2/account.json
this fails, since it’s not what the API expects. Is there a way to use my keys to make a similar request?