Microsoft Graph REST API invalid client secret - azure

I have the following POST call I need to make. However, even if I provided the right client id and secret id, my call is getting rejected.
curl POST https://login.microsoftonline.com/f02....e3/oauth2/token
-H 'Content-Type: application/x-www-form-urlencoded' --data 'grant_type=authorization_code&redirect_uri=https://requestb.in/ac&
source=https://graph.microsoft.com&client_id=1e1....-913d9
&client_secret=YmbSFYz.....4Uk=&scope=mail.read&code=AaAAA........on0a569'
This is the error I receive:
curl: (6) Could not resolve host: POST
{"error":"invalid_client","error_description":"AADSTS70002:
Error validating credentials. AADSTS50012: Invalid client secret is
provided.\r\nTrace ID: 78d...a2b\r\nCorrelation ID:
01....ab2\r\nTimestamp: 2016-12-14 01:46:47Z","error_codes":[70002,50012],"timestamp":"2016-12-14 01:46:47Z","trace_id":"78d....a2b","correlation_id":"018.....ab2"}
How could I resolve this ?
EDIT: I am trying to achieve the second section(i.e getting token) in this documentation

The post you provided is leveraging AAD V2 endpoint. But according your code snippet, you were using V1 endpoint https://login.microsoftonline.com/f02....e3/oauth2/token. For acquire access token via V1 endpoint, you can refer to https://graph.microsoft.io/en-us/docs/authorization/app_authorization for more details.
For the V2 authorization endpoint, you may check out the endpoints you are using:
GET https://login.microsoftonline.com/common/oauth2/v2.0/authorize?...
POST https://login.microsoftonline.com/common/oauth2/v2.0/token
And also it is required a v2.0 ad application:
This article assumes a v2.0 registration, so you'll register your app on the Application Registration Portal.

It was due to client_secret. It may contain special characters.
The encodeURIComponent() function encodes a URI component.
This function encodes special characters. In addition, it encodes the following characters: , / ? : # & = + $ #
Use the below one:
encodeURIComponent(client_secret);

In my case:
in configs You have to use the client secret "Value", not ID.
This Value is visible only when it is generated. So you can copy/paste it, in this moment.
See: https://learn.microsoft.com/en-us/answers/questions/370508/getting-34invalid-client-secret-is-provided34-erro.html

I am using the npm package:
Microsoft Azure Active Directory Passport.js Plug-In
with the v1 tenant-specific endpoint.
I was initially receiving the same error message after successfully logging into Microsoft: "Invalid Client Secret".
I was using the "Application ID" as the Client Secret. Then I discovered that you need to go onto the "Settings" tab in the Microsoft Azure Portal
Microsoft Azure
and create a new "Key". It doesn't matter what you name the key. When you click the "Save" button, the value of the key will be filled in the web form. Copy this right away, since it will not be displayed again if the web page is refreshed.
This is the "Client Secret" that you need to add to your configuration.

I hade the same problem today and with help of #muthu I sorted it out.
When client secret is generated with app registration in azure. The secret is plain. But when to use it in the rest call you must urlencode it.
Use an encoder like visual code or other. But it must be encoded else you ge the error
AADSTS7000215: Invalid client secret is provided.

You need to base 64 encode client_secret in the POST body.
For example (using curl):
# Authn details
LoginURL='https://login.microsoftonline.com'
TenantDomain='********.onmicrosoft.com'
ClientID='********'
ClientSecret='********'
# Endpoint details
Resource='https://graph.microsoft.com'
TenantGUID="********"
# Authenticate with OAuth v1
URL="$LoginURL/$TenantDomain/oauth2/token?api-version=1.0"
json=`
curl \
-s \
-k \
-X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "$ClientID:$ClientSecret" \
-d "grant_type=client_credentials" \
-d "resource=$Resource" \
-d "client_id=$ClientID" \
--data-urlencode "client_secret=$ClientSecret" \
$URL \
| python -m json.tool
`
access_token=`echo $json | python -c 'import sys, json; print json.load(sys.stdin)["access_token"]'`
token_type=`echo $json | python -c 'import sys, json; print json.load(sys.stdin)["token_type"]'`
#echo "access_token:$access_token"
#echo "token_type:$token_type:"
# Access resource
URL="$Resource/v1.0/directoryRoles/$TenantGUID/members"
curl \
-s \
-k \
-X GET \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: $token_type $access_token" \
$URL \
| python -m json.tool

Related

Does Github still allow private raw file access with PAT in URL

I used to be able to make the following call with a Personal Access Token (the classic token)
curl https://$PAT#raw.githubusercontent.com/$ORG/$REPO/master/$FILE
But now I just get the Github default 404 response.
If I follow a different approach the the file is accessible.
curl -H 'Authorization: token $PAT' \
-H 'Accept: application/vnd.github.v3.raw' \
-O -L https://api.github.com/$ORG/$REPO/master/$FILE
I can't find anything in the docs that states the old curl URL request has been removed. Has this method now been removed?

How can I get userId after call create user api in keycloak?

I implemented keycloak in my node.js project and call following API for add user in keycloak:
{{keycloak_url}}/admin/realms/{{realm}}/users
This API works and I can add user in keycloak but I need userId in response to this API how can I get this, any alternative way for this
Thanks in advance
I believe there is another way to do this which will save you an extra request. If you take a look at the reponse headers when you create a user, you should find a field named "Location". It looks like this:
Location: http://keycloak_address/auth/admin/realms/realm/users/3a11cc77-9871-4f6e-805b-bf17ea79fa3a
In this case the value "3a11cc77-9871-4f6e-805b-bf17ea79fa3a" would be the new user's id.
Update: The /auth path was removed starting with Keycloak 17 Quarkus distribution. So you might need to remove the /auth from the endpoint calls presented on this answer.
You use the Keycloak Admin REST API endpoint GET /{realm}/users with the query parameter username. For instance:
GET "{{keycloak_url}}/auth/admin/realms/{{realm}}/users/?username={{username}}"
NOTE: In some Keycloak version it will return all the users with a username that matches {{username*}}. Therefore, additional filtering of the list might be necessary. For those using bash script I have uploaded to my repo one example on how to do filter currently. From the response you just need to extract the field id.
The approach pointed out first by #Sillas Reis allows to create the user and get its ID in a single call, which is more performant. However, I am not a fan of relying on non documented behavior. Nonetheless, for those using bash and curl that solution could look like the following:
Call the Keycloak Admin REST API with an access token from a user with the proper permissions. For now, I will be using the admin user from the master realm:
curl “https://${KEYCLOAK_HOST}/auth/realms/master/protocol/openid-connect/token” \
-d "client_id=admin-cli" \
-d "username=${ADMIN_NAME}” \
-d "password=${ADMIN_PASSWORD}" \
-d "grant_type=password"
You get a JSON response with the admin's token. Extract the value of property access_token from that response. Let us save it in the variable $ACCESS_TOKEN for later reference.
To create the user in your realm $REALM_NAME and get back its id execute:
URL="https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/"
curl --include -X -s POST "${URL}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "$USER_JSON" | grep "Location: ${URL}" | grep -o '[^/]\+$'
the flag --include will make curl include the headers, and the command grep "Location: ${URL}" will extract the location and the command grep -o '[^/]\+$' the user ID from that location.

How to get key from Azure KeyVault as a plain text?

I have created key in Key Vault and manually imported private key in it. Now I want to retrieve using shell programing.
I have followed https://learn.microsoft.com/en-us/rest/api/keyvault/getkey/getkey and trying to retrieve the plain text but I am getting below error
curl https://test-poc-kv-31.vault.azure.net/keys/sftp/ec8368364d1844c908234396e8f50344e68?api-version=7.1
{"error":{"code":"Unauthorized","message":"Request is missing a Bearer or PoP token."}}
Not sure how to get the Bearer token for my URL?
The error message is quite clear, Request is missing a Bearar or Pop token.
Steps to create the token:
create a service principal using this command -
az ad sp create-for-rbac
grab appId from the output command and provide permissions to this service principal :
Grab password, appId and tenant from the above command and replace with the following:
curl --location --request POST 'https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id={appId}' \
--data-urlencode 'client_secret={password}' \
--data-urlencode 'scope=https://vault.azure.net/.default'
Get access_token from the responding command and pass it to this command:
curl -s "https://test-poc-kv-
31.vault.azure.net/keys/sftp/ec8368364d1844c908234396e8f50344e68?api-version=7.1" -H
"Authorization: Bearer %access_token%"
instead of using curl, you can use Azure CLI ( and make your life much easier ) :
az keyvault key show --name "%KEY_NAME%" --vault-name "VAULT_NAME"

How does urllib.request differ from curl or httpx in behaviour? Getting a 401 in a request to the Google Container Registry

I am currently working on some code to interact with images on the Google Container Registry. I have working code both using plain curl and also httpx. I am trying to build a package without 3rd party dependencies. My curiosity is around a particular endpoint from which I get a successful response in curl and httpx but a 401 Unauthorized using urllib.request.
The bash script that demonstrates what I'm trying to achieve is the following. It retrieves an access token from the registry API, then uses that token to verify that the API indeed runs version 2 and tries to access a particular Docker image configuration. I'm afraid that in order to test this, you will need access to a private GCR image and a digest for one of the tags.
#!/usr/bin/env bash
set -eu
token=$(gcloud auth print-access-token)
image=...
digest=sha256:...
get_token() {
curl -sSL \
-G \
--http1.1 \
-H "Authorization: Bearer ${token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--data-urlencode "scope=repository:$1:pull" \
--data-urlencode "service=gcr.io" \
"https://gcr.io/v2/token" | jq -r '.token'
}
echo "---"
echo "Retrieving access token."
access_token=$(get_token ${image})
echo
echo "---"
echo "Testing version 2 capability with access token."
curl -sSL \
--http1.1 \
-o /dev/null \
-w "%{http_code}" \
-H "Authorization: Bearer ${access_token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
https://gcr.io/v2/
echo
echo "---"
echo "Retrieving image configuration with access token."
curl -vL \
--http1.1 \
-o /dev/null \
-w "%{http_code}" \
-H "Authorization: Bearer ${access_token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"https://gcr.io/v2/${image}/blobs/${digest}"
I additionally created two Jupyter notebooks demonstrating my solutions in httpx and bare urllib.request. The httpx one works perfectly while somehow urllib fails on the image configuration request. I'm running out of ideas trying to spot the difference. If you run the notebook yourself, you will see that the called URL contains a token as a query parameter (is this a security issue?). When I open that link I can actually successfully download the data myself. Maybe urllib still passes along the Authorization header with the Bearer token making that last call fail with 401 Unauthorized?
Any insights are greatly appreciated.
I did some investigation and I believe the difference is that the last call to "https://gcr.io/v2/${image}/blobs/${digest}" actually contains a redirect. Inspecting the curl and httpx calls showed me that both do not include the Authorization header in the second, redirected request, whereas in the way that I set up the urllib.request in the notebook, this header is always included. It's a bit odd that this leads to a 401 but now I know how to address it.
Edit: I can now confirm that by building a urllib.request.Request instance and unlike in the linked notebook, add the authorization header with the request's add_unredirected_header method, everything works as expected.

OneLogin access token request not working (unauthorized)

I just setup a OneLogin account and wish to do a basic test from the command line with curl according to the docs at
https://developers.onelogin.com/api-docs/1/getting-started/working-with-api-credentials
and
https://developers.onelogin.com/api-docs/1/oauth20-tokens/generate-tokens-2
I get "unauthorized" despite many permutations of the curl command. Let me start with the curl command as included in the docs in the second link above. I do this:
curl 'https://api.us.onelogin.com/auth/oauth2/v2/token' \
-X POST \
-H "Authorization: client_id:144a1200f765fc67f1e, client_secret:d2dc92524169ee2" \
-H "Content-Type: application/json" \
-d '{
"grant_type":"client_credentials"
}'
(fake client_id and client_secret is included so that you can see the form they take in my call, i.e., spaces, encoding, etc.)
Response:
{"status":{"error":true,"code":401,"type":"Unauthorized","message":"Authentication Failure"}}
So I tried everything I could think of in terms of the "Authorization" line. Here are some examples of what I tried:
# base64 encode just the client_id and the client_secret (i.e., separately encoded and independent)
Authorization: client_id:zODU1NjYwOTRiZjYwOWFiOWJiZDQ1NGZjNg==, client_secret:WIxY2NjZWJjNWJlZDJlZDdiYmFiMDZiYTkyNzY3M2IxZQ==
# result: unauthorized
# base64 encode "Basic <client_id:client_secret>"
Authorization: Basic NjllZTIxZGRjOWU5YjFjY2NlYmM1YmVkMmVkN2JiYWIwNmJhOTI3NjczYjFl
# result: unauthorized
# use Basic without base64 encoding id and secret
Authorization: Basic 094bf609ab9bbd454fc6:c5bed2ed7bbab06ba927673b1e
# result: unauthorized
And finally... here is an image of the credentials page to demonstrate that I indeed did create the id and secret in the proper place.
I'm embarrassed to give the solution to this answer and there is no way from the question anyone could have answered this correctly except by guessing.
I accidentally swapped the client_id and client_secret early in my work flow and never went back to double check them... or at least if I did double check them I made the same error twice.
My best guess for why I swapped them is that they appear in one order (client_id, client_secret) in the docs and API, and they appear in the reverse order in the OneLogin UI (client_secret, client_id). You can see this in my OP.
The correct curl command is the first one I gave in the answer... plain text client id and secret (not base64 encoded). Here it is again for reference:
curl 'https://api.us.onelogin.com/auth/oauth2/v2/token' \
-X POST \
-H "Authorization: client_id:bed2ed7bbab06ba927673b1e, client_secret:385566094bf609ab9bbd454fc6" \
-H "Content-Type: application/json" \
-d '{
"grant_type":"client_credentials"
}'

Resources