SendGrid Invite Teammate via API 3.0 - sendgrid
I'm trying to invite users to my SendGrid subscription via API.
To do so, I've created a FULL ACCESS key.
If I try to create a user with the TeamMates api ( https://sendgrid.com/docs/API_Reference/Web_API_v3/teammates.html ) I receive a "forbidden" response.
If I ask the system about my key:
GET https://api.sendgrid.com/v3/api_keys/[KEY_ID]
I get a list of permissions:
{
"api_key_id": "__ID__",
"name": "__NAME__",
"scopes": [
"alerts.create",
"alerts.read",
"alerts.update",
"alerts.delete",
"asm.groups.create",
"asm.groups.read",
"asm.groups.update",
"asm.groups.delete",
"ips.pools.ips.read",
"mail.send",
"mail_settings.bcc.read",
"mail_settings.bcc.update",
"mail_settings.address_whitelist.read",
"mail_settings.address_whitelist.update",
"mail_settings.footer.read",
"mail_settings.footer.update",
"mail_settings.forward_spam.read",
"mail_settings.forward_spam.update",
"mail_settings.plain_content.read",
"mail_settings.plain_content.update",
"mail_settings.spam_check.read",
"mail_settings.spam_check.update",
"mail_settings.bounce_purge.read",
"mail_settings.bounce_purge.update",
"mail_settings.forward_bounce.read",
"mail_settings.forward_bounce.update",
"partner_settings.new_relic.read",
"partner_settings.new_relic.update",
"partner_settings.sendwithus.read",
"partner_settings.sendwithus.update",
"tracking_settings.click.read",
"tracking_settings.click.update",
"tracking_settings.subscription.read",
"tracking_settings.subscription.update",
"tracking_settings.open.read",
"tracking_settings.open.update",
"tracking_settings.google_analytics.read",
"tracking_settings.google_analytics.update",
"user.webhooks.event.settings.read",
"user.webhooks.event.settings.update",
"user.webhooks.event.test.create",
"user.webhooks.event.test.read",
"user.webhooks.event.test.update",
"user.webhooks.parse.settings.create",
"user.webhooks.parse.settings.read",
"user.webhooks.parse.settings.update",
"user.webhooks.parse.settings.delete",
"stats.read",
"stats.global.read",
"categories.stats.read",
"categories.stats.sums.read",
"devices.stats.read",
"clients.stats.read",
"clients.phone.stats.read",
"clients.tablet.stats.read",
"clients.webmail.stats.read",
"clients.desktop.stats.read",
"geo.stats.read",
"mailbox_providers.stats.read",
"browsers.stats.read",
"user.webhooks.parse.stats.read",
"templates.create",
"templates.read",
"templates.update",
"templates.delete",
"templates.versions.create",
"templates.versions.read",
"templates.versions.update",
"templates.versions.delete",
"templates.versions.activate.create",
"user.timezone.read",
"user.timezone.update",
"user.settings.enforced_tls.read",
"user.settings.enforced_tls.update",
"api_keys.create",
"api_keys.read",
"api_keys.update",
"api_keys.delete",
"email_activity.read",
"categories.create",
"categories.read",
"categories.update",
"categories.delete",
"mail_settings.template.read",
"mail_settings.template.update",
"marketing_campaigns.create",
"marketing_campaigns.read",
"marketing_campaigns.update",
"marketing_campaigns.delete",
"mail.batch.create",
"mail.batch.read",
"mail.batch.update",
"mail.batch.delete",
"user.scheduled_sends.create",
"user.scheduled_sends.read",
"user.scheduled_sends.update",
"user.scheduled_sends.delete",
"access_settings.whitelist.create",
"access_settings.whitelist.read",
"access_settings.whitelist.update",
"access_settings.whitelist.delete",
"access_settings.activity.read",
"whitelabel.create",
"whitelabel.read",
"whitelabel.update",
"whitelabel.delete",
"suppression.create",
"suppression.read",
"suppression.update",
"suppression.delete"
]
}
But there is no "user-related" permissions. For this reason I tried to "change" my Key permission like:
{
"name": "__NAME__",
"scopes": [
"alerts.create",
"alerts.read",
"alerts.update",
"alerts.delete",
"asm.groups.create",
"asm.groups.read",
"asm.groups.update",
"asm.groups.delete",
"ips.pools.ips.read",
"mail.send",
"mail_settings.bcc.read",
"mail_settings.bcc.update",
"mail_settings.address_whitelist.read",
"mail_settings.address_whitelist.update",
"mail_settings.footer.read",
"mail_settings.footer.update",
"mail_settings.forward_spam.read",
"mail_settings.forward_spam.update",
"mail_settings.plain_content.read",
"mail_settings.plain_content.update",
"mail_settings.spam_check.read",
"mail_settings.spam_check.update",
"mail_settings.bounce_purge.read",
"mail_settings.bounce_purge.update",
"mail_settings.forward_bounce.read",
"mail_settings.forward_bounce.update",
"partner_settings.new_relic.read",
"partner_settings.new_relic.update",
"partner_settings.sendwithus.read",
"partner_settings.sendwithus.update",
"tracking_settings.click.read",
"tracking_settings.click.update",
"tracking_settings.subscription.read",
"tracking_settings.subscription.update",
"tracking_settings.open.read",
"tracking_settings.open.update",
"tracking_settings.google_analytics.read",
"tracking_settings.google_analytics.update",
"user.webhooks.event.settings.read",
"user.webhooks.event.settings.update",
"user.webhooks.event.test.create",
"user.webhooks.event.test.read",
"user.webhooks.event.test.update",
"user.webhooks.parse.settings.create",
"user.webhooks.parse.settings.read",
"user.webhooks.parse.settings.update",
"user.webhooks.parse.settings.delete",
"stats.read",
"stats.global.read",
"categories.stats.read",
"categories.stats.sums.read",
"devices.stats.read",
"clients.stats.read",
"clients.phone.stats.read",
"clients.tablet.stats.read",
"clients.webmail.stats.read",
"clients.desktop.stats.read",
"geo.stats.read",
"mailbox_providers.stats.read",
"browsers.stats.read",
"user.webhooks.parse.stats.read",
"templates.create",
"templates.read",
"templates.update",
"templates.delete",
"templates.versions.create",
"templates.versions.read",
"templates.versions.update",
"templates.versions.delete",
"templates.versions.activate.create",
"user.timezone.read",
"user.timezone.update",
"user.settings.enforced_tls.read",
"user.settings.enforced_tls.update",
"api_keys.create",
"api_keys.read",
"api_keys.update",
"api_keys.delete",
"email_activity.read",
"categories.create",
"categories.read",
"categories.update",
"categories.delete",
"mail_settings.template.read",
"mail_settings.template.update",
"marketing_campaigns.create",
"marketing_campaigns.read",
"marketing_campaigns.update",
"marketing_campaigns.delete",
"mail.batch.create",
"mail.batch.read",
"mail.batch.update",
"mail.batch.delete",
"user.scheduled_sends.create",
"user.scheduled_sends.read",
"user.scheduled_sends.update",
"user.scheduled_sends.delete",
"access_settings.whitelist.create",
"access_settings.whitelist.read",
"access_settings.whitelist.update",
"access_settings.whitelist.delete",
"access_settings.activity.read",
"whitelabel.create",
"whitelabel.read",
"whitelabel.update",
"whitelabel.delete",
"suppression.create",
"suppression.read",
"suppression.update",
"suppression.delete",
"user.account.read",
"user.credits.read",
"user.email.create",
"user.email.delete",
"user.email.read",
"user.email.update"
]
}
But I had no luck:
{
"errors": [
{
"field": null,
"message": "unauthorized scopes: [user.account.read user.credits.read user.email.create user.email.delete user.email.read user.email.update]"
}
]
}
Is there any way to INVITE with API KEY some users to SendGrid? Is something I'm doing wrong or related to my plan?
Thanks
The response was in the docs, summarizing:
You must creating superpower API KEY with Username + Password and then use them.
From:
https://sendgrid.com/docs/Classroom/Basics/API/api_key_permissions.html
"Important things to know before making the above API request:
You will need to authenticate the above request with your parent account’s username and password because your API key will not have the required API key permissions. There are two ways to authenticate using your username and password:
You can add basic authorization to your API call yourself by base64 encoding your username and password like this: username:password and adding it to your Authorization header as Basic. We go into a little more detail on this here.
Or you can use a rest client like Postman or Paw, where you can select to Authenticate with basic auth (your SendGrid parent account username and password) then update the request to add your parent account credentials encoded into the headers.
We only recommend authenticating with your username and password when updating your API Key permissions. All other API calls should be authenticated via your API Key.
Make sure that when you make the request, you add all of the scopes you want the API key to have. For example, if you make the request and just list “categories.read” as the scopes, you will then have a key with only the “categories.read” scope. Make sure to list everything you get from the get existing key request in addition to the new scopes you want to add.
Related
authlib.jose.errors.InvalidClaimError: invalid_claim: Invalid claim "iss"
I'm building an oauth2 client with Flask and Authlib. My code to register the oauth is: google = oauth.register( name='google', client_id='', client_secret="", access_token_url="https://accounts.google.com/o/oauth2/token", access_token_params=None, authorize_url="https://accounts.google.com/o/oauth2/auth", authorize_params=None, api_base_url="https://www.googleapis.com/oauth2/v1/", client_kwargs={'scope': 'openid email'}, server_metadata_url="https://accounts.google.com/.well-known/openid-configuration", ) And my /authorize endpoint looks like this: #app.route('/authorize') def authorize(): google = oauth.create_client('google') token = google.authorize_access_token() resp = google.get('userinfo') resp.raise_for_status() userinfo = resp.json() return str(userinfo) But I am getting the error authlib.jose.errors.InvalidClaimError: invalid_claim: Invalid claim "iss"
I had this issue and removing the openid value from scope fixed it. I guess my google config didn't accomodate it,
Connecting to Facebook's API
I am facing this issue connecting with Facebook's API using httr package, while testing on 'me' node I came along the following problem. I was under the impression that me node does not require special permissions. Testing on the browser with 'https://graph.facebook.com/me' gave the same results, it would be great if some one could provide an explanation. # Define keys app_id = 'my_app_id' app_secret = 'my_app_secret' # Define the app fb_app <- oauth_app(appname = "facebook", key = app_id, secret = app_secret) # Get OAuth user access token fb_token <- oauth2.0_token(oauth_endpoints("facebook"), fb_app, scope = 'public_profile', type = "application/x-www-form-urlencoded", cache = TRUE) response <- GET("https://graph.facebook.com", path = "/me", config = config(token = fb_token)) # Show content returned content(response) $error $error$message [1] "An active access token must be used to query information about the current user." $error$type [1] "OAuthException" $error$code [1] 2500 $error$fbtrace_id [1] "ARRnb93rZHmWLlXK_MMJlfi" Noting that I have signed in using the app.
How to access custom header from AWS Lambda Authorizer?
I have created an Authorizer in AWS API Gateway. This Authorizer refers to a Lambda Function. I am passing the following values in header, to the API Endpoint using Postman. { "type":"TOKEN", "authorizationToken": "testing2", "methodArn": "arn:aws:execute-api:us-west-2:444456789012:ymy8tbxw7b/*/GET/" } The above header values are received in the Lambda Function. I can see this through the logs in CloudWatch. I want to pass additional value 'clientID' in the header. So I pass the following values in the header from postman. { "type":"TOKEN", "authorizationToken": "testing2", "methodArn": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/", "clientID" : "1000" } In this case, the Lambda function does not get the clientID. I checked various threads in SO, and understood that this can be achieved mapping header. So I did the following. In the "Method Execution" section of the API method, I created a new header clientID. In the "Integration Request" section, under "HTTP Headers" section I provided the following value Name: clientID Mapped from: method.request.header.clientID After doing the above, I deployed the API and tried to call the method from Postman, but the clientID is shown undefined. Following is the code that I have written in Lambda Function exports.handler = function(event, context, callback) { var clientid = event.clientID; //I always get event.clientID undefined console.log("The client ID is:" + event.clientID); } EDIT Following is the error from the CloudWatch Log. START RequestId: 274c6574-dea5-4009-b777-a929f84b9a9d Version: $LATEST 2019-09-19T09:40:25.944Z 274c6574-dea5-4009-b777-a929f84b9a9d INFO The client ID is:undefined 2019-09-19T09:40:25.968Z 274c6574-dea5-4009-b777-a929f84b9a9d ERROR Invoke Error { "errorType": "Error", "errorMessage": "Unauthorized", "stack": [ "Error: Unauthorized", " at _homogeneousError (/var/runtime/CallbackContext.js:13:12)", " at postError (/var/runtime/CallbackContext.js:30:51)", " at callback (/var/runtime/CallbackContext.js:42:7)", " at /var/runtime/CallbackContext.js:105:16", " at Runtime.exports.handler (/var/task/index.js:40:4)", " at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)", " at process._tickCallback (internal/process/next_tick.js:68:7)" ] }
I have understood why I was not getting the value in the header. I have done the following 1) Instead of type TOKEN, I used type REQUEST in the header. I understood this by reading the following link. This link also contains code for Request type. https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html 2) I removed all the mapping from Method Request and Integration Request. 3) Deployed the API.
getting NoAuthorization Header Missing Exception while using flask-jwt-extended
When I try this example and if the jet token is not provided by header I get error: { "msg": "Missing cookie \"access_token_cookie\"" } example: from flask import Flask, jsonify, request from flask_jwt_extended import ( JWTManager, jwt_required, create_access_token, jwt_refresh_token_required, create_refresh_token, get_jwt_identity, set_access_cookies, set_refresh_cookies, unset_jwt_cookies ) from flask_jwt_extended.config import config # NOTE: This is just a basic example of how to enable cookies. This is # vulnerable to CSRF attacks, and should not be used as is. See # csrf_protection_with_cookies.py for a more complete example! app = Flask(__name__) # Configure application to store JWTs in cookies. Whenever you make # a request to a protected endpoint, you will need to send in the # access or refresh JWT via a cookie. app.config['JWT_TOKEN_LOCATION'] = ['cookies'] # Set the cookie paths, so that you are only sending your access token # cookie to the access endpoints, and only sending your refresh token # to the refresh endpoint. Technically this is optional, but it is in # your best interest to not send additional cookies in the request if # they aren't needed. app.config['JWT_ACCESS_COOKIE_PATH'] = '/api/' app.config['JWT_REFRESH_COOKIE_PATH'] = '/token/refresh' # Disable CSRF protection for this example. In almost every case, # this is a bad idea. See examples/csrf_protection_with_cookies.py # for how safely store JWTs in cookies app.config['JWT_COOKIE_CSRF_PROTECT'] = False # Set the secret key to sign the JWTs with app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this! jwt = JWTManager(app) # Use the set_access_cookie() and set_refresh_cookie() on a response # object to set the JWTs in the response cookies. You can configure # the cookie names and other settings via various app.config options #app.route('/token/auth', methods=['POST']) def login(): # username = request.json.get('username', None) # password = request.json.get('password', None) # if username != 'test' or password != 'test': # return jsonify({'login': False}), 401 # print dir(config) # Create the tokens we will be sending back to the user access_token = create_access_token(identity="test") refresh_token = create_refresh_token(identity="test") # Set the JWT cookies in the response resp = jsonify({'login': True, "cookie_key": config.access_cookie_name, "cooke_value": access_token}) set_access_cookies(resp, access_token) set_refresh_cookies(resp, refresh_token) return resp, 200 # Same thing as login here, except we are only setting a new cookie # for the access token. #app.route('/token/refresh', methods=['POST']) #jwt_refresh_token_required def refresh(): # Create the new access token current_user = get_jwt_identity() access_token = create_access_token(identity=current_user) # Set the JWT access cookie in the response resp = jsonify({'refresh': True}) set_access_cookies(resp, access_token) return resp, 200 # Because the JWTs are stored in an httponly cookie now, we cannot # log the user out by simply deleting the cookie in the frontend. # We need the backend to send us a response to delete the cookies # in order to logout. unset_jwt_cookies is a helper function to # do just that. #app.route('/token/remove', methods=['POST']) def logout(): resp = jsonify({'logout': True}) unset_jwt_cookies(resp) return resp, 200 # We do not need to make any changes to our protected endpoints. They # will all still function the exact same as they do when sending the # JWT in via a header instead of a cookie #app.route('/api/example', methods=['GET']) #jwt_required def protected(): username = get_jwt_identity() return jsonify({'hello': 'from {}'.format(username)}), 200 if __name__ == '__main__': app.run(debug=True) But in my office I have similar setup except I am not calling username = get_jwt_identity() I get NoAuthorization exception get raised. how does this work ...
It's mean you not login and flask-jwt can't find any token on your cookies. Do you login before call this resource? check your cookie that returned from app.
In my case it was CORS error, I was using a different api address from the website
How to use gspread with python-social-auth
I'm trying to use gspread with python-social-auth, I followed the sample describe on documentation and I've created this class to use as credential store: class Credentials(object): def __init__ (self, access_token=None, scope=None): self.access_token = access_token self.scope=scope def refresh (self, http): # get new access_token # this only gets called if access_token is None pass And at my code I've used: import gspread credentials = Credentials(access_token=user.social_auth.get_access_token(), scope=['https://spreadsheets.google.com/feeds']) sh = gspread.authorize(credentials) And asking any response from API using: sh.get_spreadsheets_feed() This error appears on the console: *** RequestError: (401, '401: <HTML>\n<HEAD>\n<TITLE>Token invalid - AuthSub token has wrong scope</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>Token invalid - AuthSub token has wrong scope</H1>\n<H2>Error 401</H2>\n</BODY>\n</HTML>\n') I have defined the scope at my settings and this is working well, for example trying to get contacts from Google Contacts SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [ 'https://www.googleapis.com/auth/contacts.readonly', 'https://www.googleapis.com/auth/spreadsheets.readonly' ] Any ideas?
You have to add these scopes also to Python Social Auth settings: SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [ ... 'https://www.googleapis.com/auth/spreadsheets.readonly', 'https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive.file' ]