Snowflake SQL API - JWT token is invalid - snowflake-cloud-data-platform

I'm new to Snowflake and my objective is to use the SQL API to execute queries.
Using curl I'm able to create an access token and a refresh token. I can then use the access token in the snowsql connection parameter "--token" to start a snowsql session and execute SQL statements. This all works fine.
However, when I try to use curl to POST a request to the /api/statements endpoint (as documented on https://docs.snowflake.com/en/developer-guide/sql-api/guide.html#example-of-a-request) and I use the same access token, then I'm getting an "JWT token is invalid" error.
Am I missing something here? Do I need to generate and use a different access token for the SQL API than the one I can use with snowsql?
If so, how can I generate such access token?
Any idea or hint is greatly appreciated.
Thanks.

There are 2 mechanisms for authorizing the users for SQL API, one is the External Oauth and the other is key-pair mechanism.
From what I presume, it seems that you have used the External OAuth token for Key pair auth for SQL API hence the error is seen.
In the SQL API request that is being tested, remove this line:
-H "X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT" \
Now, run the curl command and it should work successfully.
When no parameter value for Auth token type is passed, it defaults to external OAuth.

Related

standard format for named credentials authentication response?

Am trying to utilise Salesforce named credentials (legacy) to connect to a custom built external API, and seeking guidance for what (or where to find) the format of the 'standard' auth response Salesforce expects in order for it to then be able to extract returned tokens etc for use in subsequent callouts.
Currently, the response from the auth endpoint Im hitting is in JSON format payload returned in response body. I have to parse the json for my access token, and then (I guess) store that token for subsequent use. Is this typical, or am I not using named credentials properly? Is token management my responsibility or ideally part of what named credentials manages?
I'd have thought that once I hit the auth endpoint and got sent a token in some 'expected' response format, salesforce named credentials would store and pass that token in any subsequent callouts - or do I have it all wrong?
Any pointers most appreciated!

"code": "390100" Incorrect Username Password specified when trying to connect to SQL API from Postman using Oauth

I am getting the below error when trying to make a connection to the snowflake.
{
"code": "390100",
"message": "Incorrect username or password was specified."
}
The same works well when I generate the token via cli and use the same to connect to snowflake. This issue is happening when I use Oauth.
Does any one has info on this?
Check the official documentation below.
https://docs.snowflake.com/en/developer-guide/sql-api/submitting-requests.html#label-sql-api-submit-query-regionless-account
Snowflake-Account header must be passed and this must be the account locator (which you can find under your username when you connect to snowflake UI).
For example:
when you connect to snowflake, there are two URL's that can be utilized.
Regionless :--> https://organizationname-accountname.snowflakecomputing.com
With Region :-> https://Account_locator.us-east-2.snowflakecomputing.com
When you are using a Regionless URL and the authentication type as OAUTH, then you need to pass an additional header.
"Snowflake-Account: "
In postman you can pass the parameter under headers with key and value way, where key being Snowflake-Account and value being Account Locator.
If you don't use regionless URL, the above header is not needed.
Let me know if the above helps. Also attaching KB article for your reference to setup with postman.
https://community.snowflake.com/s/article/Connect-to-SQL-API-using-Postman

Amazon SP API getting internal server error

I am trying to get access token from api https://api.amazon.com/auth/o2/token
POST /auth/o2/token HTTP/l.l
Host: api.amazon.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
grant_type=refresh_token
&refresh_token=Aztr|...
&client_id=foodev
&client_secret=Y76SDl2F
But after POST request I get 500 server error.
Is it because my app is in draft status? or I am missing something while making request?
If it because of draft status then when the status will get change? any thoughts on this.
Thank you for your help in advance.
The documentation is wrong. I was getting the same exact error and came across this comment on a github issue which mentioned that the data has to be passed into the body of the request, not as query string parameters. Sure enough, this worked for me and I was able to get an access token. So just to clarify: grant_type, refresh_token, client_id, and client_secret should be passed into the body of the POST request to https://api.amazon.com/auth/o2/token and NOT as query string parameters.
Draft status will not keep you from requesting and receiving the access token.
Here are a few things to check as not much can be derived from the example post request from the documentation:
Did you configure AWS IAM role / policy / user properly
Did you use the correct IAM ARN when registering the application
Are you using the correct LWA credentials (I am assuming you're not passing foodev and Y76SDl2F as those are example parameters)
Have you self authorized the application (are you using the refresh token generated
for the authorized application)
Are you 'assuming the role' before the token exchange -- this is a very important step
and is very different in comparison to how access was handled with MWS -- if
you have not, the server will reject the token exchange regardless if the refresh
token is correct. More on that here
This is a non-exhaustive list, just some common issues I have seen other developers have with getting the access token during development, if these don't work you'll need to work with support as they can see the requests hitting the token endpoint.

What Scope and or resource to set to get token that works with office 365 api?

We have acquired the Admin consent in both delegated and application ServiceHealth.Read permissions in Office 365 Management API for our Client app in Azure AD.
We are unable to figure out what the scope and or resource needs to be in token acquisition process if we want to make calls to the office365 management api.
Whether its the client_credentials grant method of direct token acquisition
Or the authorization code then token for signed-in user method
It would be preferable if its for the client_credentials grant method, but if it has to be through auth code, that's fine too.
We can use the following already to grab our reports but do not know how to allow that authentication to also cover Office365 Management API Service Health
curl --location --request GET "https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data "client_id={clientid}&client_secret={clientsecret}&scope=https://graph.microsoft.com/.default&grant_type=client_credentials"
When adding ServiceHealth.Read to the end or by itself it returned invalid_scope as an error
When place only https://manage.office.com/ServiceHealth.Read/.default in the scope it gives the error invalid_resource with the description including that the resource not found in tenant
A similar problem occurred when trying to get the authorization code and setting the resource as ServiceHealth.Read and while setting that as the scope instead gave a authorization code, the resulting token was deemed invalid.
Authorization Code Grant Flow
I quickly tried this out with an Azure AD app registration that has ServiceHealth.Read delegated permission for Office 365 Management APIs.
Scope value used - https://manage.office.com/ServiceHealth.Read
I was able to successfully get back an access token following the Authorization Code Grant flow. I'll share the detailed request parameters passed shortly, but this should answer your direct question about what scope value to use.
Since I used Azure AD V2 endpoints, I didn't really need to specify a resource. In your sample requests mentioned in question I see that you are also using Azure AD V2 endpoint.
Detailed steps
Step 1 - Get the Authorization Code
For this step, I directly used browser and then sign in using a valid user from my Azure AD tenant.
// Line breaks only for clear reading. Remove line breaks and paste in browser URL to test.
https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?
client_id=29a95b.....
&response_type=code
&redirect_uri=https://rohitapp/
&response_mode=query
&scope=https://manage.office.com/ServiceHealth.Read
&state=12345
Response should be something like
https://rohitapp/?code=
OAQABAAIAAACQN9QBRU....
&state=12345&session_state=f5da06....
Step 2 - Acquire Token from token endpoint
Take the Authorization code from last step.
For this step I used POSTMAN. You can use CURL as well.
POST https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Request Body
client_id=29a95b....
&scope=https://manage.office.com/ServiceHealth.Read
&code=OAQABAAIAAACQN9QBRU....
&redirect_uri=https://rohitapp/
&grant_type=authorization_code
&client_secret=Aj....
Final Token received, decoded in https://jwt.ms
Client Credentials Grant Flow
Scope value used - https://manage.office.com/.default
I did add the related app permission and give consent for it.
For this one I used POSTMAN again. You can use CURL as well.
POST https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
Request Body
client_id=29a95....
&scope=https://manage.office.com/.default
&grant_type=client_credentials
&client_secret=Aj....
Final Token received, decoded in https://jwt.ms
Take a look at this Microsoft documentation around scope value for Client Credentials Grant.

How can you implement refresh tokens in a web app - angularjs

I am using token based security in my web app. The server side is wrote using c# and i am using openiddict for logging in and issuing tokens, found here. I am currencyly using Implict flow.
By default my tokens have a lifespan of 1 hour, after that you have to logging again. I have locked down my API to accept bearer tokens only and not cookies.
I wanted to implement refresh tokens but after reading many websites, it appears that implementing refresh tokens on a web app, is not a good way to go due to a hacker getting the refresh token. I know that to use refresh tokens, you must use code flow, instead of implict, which i can do.
How do people get round this situation in their web apps? I cant be the only one who wants a token to last longer than an hour in a web app?
The approach recommended by OpenID Connect is to send an authorization request in a hidden frame with the same parameters as the ones you use for the initial implicit flow request plus prompt=none and optionally, an id_token_hint corresponding to the id_token you extracted from the authorization response.
When using prompt=none, the identity provider won't display any consent form and will directly redirect the user agent to the redirect_uri you specify, with the new token appended to the URI fragment, just like for a classic implicit flow request. You can retrieve it by extracting it from the popup.location.hash property.
If the request cannot be processed (invalid request, unauthenticated user, invalid id_token_hint, consent required, etc.), an error is returned and the identity provider either redirects the user agent to the redirect_uri with an error parameter or stops processing the request.
Note that due to the same origin policy, you can't access popup.location.hash if the current location belongs to a different domain (e.g if the identity provider refuses to redirect the user agent to your client app): it will throw an access denied exception. In this case, it's always better to add a timeout to your "refresh" operation.
Sadly, there are very few libraries that can help you with this task. oidc-token-manager is one of them, but it has a few limitations that will prevent it from working OTB with OpenIddict: it doesn't support raw RSA keys (you have to explicitly use a X509 certificate in the OpenIddict options) and it doesn't send the id_token_hint parameter required by OpenIddict when sending a prompt=none request.

Resources