Access Azure Key Vault using Service-to-Service Access Token via REST - azure

I am having trouble getting enough permission to access Azure Key Vault using my app ( and not via user login ). Here is my setup:
I have a azure key vault setup:
I have given my app called "KeyVault" every permission.
My app is registered with Azure Active Directory. And I have give it permission to access the Key Vault:
After all this, I try to get an Access Token using the following REST API:
https://login.microsoftonline.com/<DOMAIN_ID>/oauth2/token
The client_id and resource are both the App ID of my registered app in Active Directory I showed earlier. ( is this correct? )
I do get an Access Token back, which I use to try to query a secret in my vault. Unfortunately as you can see it return an 401 error, which is no permission. What am I doing wrong?
The URL is from the "Secret Identifier" of the secret in the key vault.

The client_id and resource are both the App ID of my registered app in
Active Directory I showed earlier.
No, the resource id is not app id. As Rich said, the value is https://vault.azure.net.
I test it in my lab with Power Shell, the code should like below:
$TENANTID=""
$APPID=""
$PASSWORD=""
$result=Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body #{"grant_type" = "client_credentials"; "resource" = "https://vault.azure.net"; "client_id" = "$APPID"; "client_secret" = "$PASSWORD" }
$token=$result.access_token
$url="https://shui.vault.azure.net/secrets/shui01/cea20d376aee4d25a2d714df19314c26?api-version=2016-10-01"
$Headers=#{
'authorization'="Bearer $token"
}
Invoke-RestMethod -Uri $url -Headers $Headers -Method GET
Note: If you want to get the API input information, you could use Azure Power Shell -debug to get it. For example:

When requesting the token from AAD you should set the resource to be:
https://vault.azure.net
That will ensure that the returned token is 'addressed' to Key Vault.

Related

Can you get an access token for Azure with a username and password and without using a client_id via web request?

Scenario: I'm trying to get an access token using a web request as I cannot use Azure PowerShell. The situation I'm trying to replicate is Get-AzAccessToken, where I've authenticated using my username and password and I'm not supplying a client_id.
I can get an access token in PowerShell using the following:
$postParams = #{
grant_type = 'password'
client_id = $ClientId
username = $Username
password = $Password
scope = 'https://graph.microsoft.com/.default'
}
Write-Host "Getting access token for app"
Invoke-RestMethod `
-Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token `
-Method POST `
-ContentType application/x-www-form-urlencoded `
-Body $postParams
I can also get an access token by using the Azure PowerShell command Get-AzAccessToken.
Is it possible to get an access token without using a client_id? If not, is Get-AzAccessToken using a client_id?
It is not possible without a client id. And yes, Azure PowerShell is using one. The best way to implement this is to register your own app and use its client id.

azure user-assigned identity for azure sql fails

I am trying to use a user assigned identity (from a Azure container instance) to connect to an Azure sql database.
following this guide:
https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-sql
it works for System assigned identities, but not for user assigned ones. when trying to create the contained user, using the user assigned identity i get this error
Msg 33134, Level 16, State 1, Line 1
Principal 'user-assigned-identity-name' could not be resolved. Error message: 'AADSTS7000219: 'client_assertion' or 'client_secret' is required for the 'urn:ietf:params:oauth:grant-type:jwt-bearer' grant type
Am i missing something here or have i misunderstood user assigned identities? Can they be used to login in to and query sql server?
The guide you followed is used for system-assigned managed identity, because it enables you to authenticate to services that support Azure AD authentication, without needing to insert credentials into your code. But credential is necessary for user-assigned managed identity.
You could refer to this, and use the way to get access_token.
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&client_id=af825a31-b0e0-471f-baea-96de555632f9&resource=https://management.azure.com/' -Method GET -Headers #{Metadata="true"}
$content = $response.Content | ConvertFrom-Json
$ArmToken = $content.access_token

Cannot set "preAuthorizedApplications" object in new App registrations module through Azure Powershell

Short Scenrario: A muti tenant front end javascript (React.JS) Web Application calls a multi tenant ASP.NET Core 2.2 WebAPI from the browser.
Authentication:
ADAL.js in the front end app takes care of getting a token from either AzureAD1 or AzureAD2 or AzureAD3... when the User signs-in (based on the User's original Azure Active Directory).
The User gives consent to the front end Web App (scope: Sign in and read user profile) which is delegated to the WebAPI too. (meaning the user does not need to consent to the WebAPI as well)
The front end Web App calls the WebAPI with the bearer token to get the resources.
Problem: I must automate the deployment of a new environment. And set the manifest file accordingly (It's a SaaS solution)
In the manifest file I need to expose the WebAPI for the client application (https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis#expose-a-new-scope-through-the-ui)
Setting "knownClientApplications" is not enough (due to previously described delegation)
The new v2 endpoint (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-overview) has a new App Registration feature. The old one is called "Legacy" now and will be deprecated starting May 2019.
In the Azure Portal need to expose the API and add the front end WebApp as an "Authorized cient applications".
This step will add a new object in the manifest file:
"preAuthorizedApplications": [
{
"appId": "guid",
"permissionIds": [
"guid"
]
}
],
But it's still not available throuh PowerShell! (https://learn.microsoft.com/en-us/powershell/module/azuread/set-azureadapplication?view=azureadps-2.0)
How can I add this "preAuthorizedApplications" section into the manifest file using Azure PowerShell? Why is it available in the portal but not in PS yet? It's the other way around usually...
08-05-2019 Update based on the answer:
I am getting the access token via a Service Principal:
$adTokenUrl = "https://login.microsoftonline.com/$TenantId/oauth2/token"
$resource = "https://graph.windows.net/"
$body = #{
grant_type = "client_credentials"
client_id = "$ServicePrincipalId"
client_secret = "$ServicePrincipalKey"
resource = "$resource"
}
$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
According to the docs: https://learn.microsoft.com/en-us/graph/api/application-update?view=graph-rest-beta&tabs=cs
The Service Principal should have at least Application.ReadWrite.OwnedBy, and most Application.ReadWrite.All privileges.
Should I ask our AAD admin to grant the below rights to the Service Principal?
08-05-2019 Update 2: Service Principal has been granted with ALL of the highlighted rights above.
Attempt 1:
Step 1: getting an access_token via the Service Principal (Owner of the Api app to be updated)
$adTokenUrl = "https://login.microsoftonline.com/$(TenantId)/oauth2/token"
$resource = "https://graph.microsoft.com/"
$body = #{
grant_type = "client_credentials"
client_id = "$(ServicePrincipalId)"
client_secret = "$(ServicePrincipalKey)"
resource = "$resource"
}
$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
Step 2: using this access_token, building up my PATCH request as per Md Farid Uddin Kiron's suggestion, and
Result: The remote server returned an error: (403) Forbidden.
09-05-2019 Update 3: After some kind and detailed explanation and guidance, I got this to work and getting HTTP 204 for my Postman request. Only thing left is to integrate this steps into my pipeline.
See accepted answer. It works. If someone has the same issue,
please read the other answer from Md Farid Uddin Kiron.
If you want to avoid calling directly the graph API (maybe you are in an azure pipeline using a Service Connection and don't have access to the credentials) you can do this :
$AppName = << WebApp >>
$preAuthorizedApplicationsAppId = <<GUID>>
# Get the application and delegated permission to pre-authorize
$appRegistration = Get-AzureADMSApplication -Filter "displayName eq '$AppName'"
$oauth2Permission = $appRegistration.Api.OAuth2PermissionScopes | Where-Object {$_.Value -eq $AppName -and $_.Type -eq 'Admin'}
# Build a PreAuthorizedApplication object
$preAuthorizedApplication = New-Object 'Microsoft.Open.MSGraph.Model.PreAuthorizedApplication'
$preAuthorizedApplication.AppId = $preAuthorizedApplicationsAppId
$preAuthorizedApplication.DelegatedPermissionIds = #($oauth2Permission.Id)
$appRegistration.Api.PreAuthorizedApplications = New-Object 'System.Collections.Generic.List[Microsoft.Open.MSGraph.Model.PreAuthorizedApplication]'
$appRegistration.Api.PreAuthorizedApplications.Add($preAuthorizedApplication)
# Update the Application object
Set-AzureADMSApplication -ObjectId $appRegistration.Id -Api $appRegistration.Api
This answer comes from this GitHub issue.
You are right, seems there is something faultiness exists in AzureAD powershell module. That not works for me too .
If you want to modify your app manifest using powershell to add "preAuthorizedApplications" section, you can try the powershell script below.
I have tested on my side and it works for me.
In theory, I have called Microsoft Graph API to modify the app manifest . If you have any further concerns, please feel free to let me know.
$AdAdminUserName = "<-your Azure ad admin username ->"
$AdAdminPass="<-your Azure ad admin password ->"
$AdAppObjId = "<-your app obj id->"
$AdPreAuthAppId = "<-the app that need to be pre authed ->"
$AdAppScopeId = "<-your app scope id->"
$tenantName = "<-your tenant name->"
$body=#{
    "grant_type"="password";
    "resource"="https://graph.microsoft.com/";
    "client_id"="1950a258-227b-4e31-a9cf-717495945fc2";
    "username"=$AdAdminUserName;
    "password" = $AdAdminPass
}
$requrl = "https://login.microsoftonline.com/"+$tenantName+"/oauth2/token"
$result=Invoke-RestMethod -Uri $requrl -Method POST -Body $body 
$headers = New-Object 'System.Collections.Generic.Dictionary[String,String]'
$headers.Add("Content-Type","application/json")
$headers.Add("Authorization","Bearer " + $result.access_token)
$preAuthBody = "{`"api`": {`"preAuthorizedApplications`": [{`"appId`": `"" + $AdPreAuthAppId + "`",`"permissionIds`": [`"" + $AdAppScopeId + "`"]}]}}"
$requrl= "https://graph.microsoft.com/beta/applications/"+$AdAppObjId
Invoke-RestMethod -Uri $requrl -Method PATCH -Body $preAuthBody -Headers $headers
Note: ROPC is not safe as Microsoft does not recommend to use that. It also does not allow to use MFA that is why it is little
dangerous.
Some additions to another reply.
Actually, in AzureADPreview powershell module, there is a parameter -PreAuthorizedApplications for Set-AzureADApplication. But neither the cmdlet help nor the documentation page has been updated to detail all these, it was also mentioned here.
I am not sure the parameter will work or not, per my test, I always get a bad request error. Even if I call the Azure AD Graph API, I get the same error. The command Set-AzureADApplication essentially calls the Azure AD Graph API, so if the parameter works, it will also work for the API. Also, in the AAD Graph doc, there is no such property. According to the test result, the parameter seems not to work currently. (not sure, if there is something wrong, please correct me)
I got this error too using client_credentials type to get access_token to call that API even though I granted all Microsoft Graph API and AAD API application related permissions. It is really weird.
However , using password flow to get access token under Azure AD admin account will be able to call this API successfully :
Update
You could get your client id and client secret by below steps
Go to azure portal on azure active directory menu see the screen
hot below:
Once you select azure active directory you would see App
registrations click on that. Then select your application. See the below picture
On your apllication you would see the client id, tenant id and
client secret which marked on the screen shot below:
If you still have any concern please feel free to share. Thank you and happy coding!
to resolve token issue I did like this(if you have az subscription owner, in this case you can get token which allows to update aad owned application properties without aad admin login and password). After az login by subscription owner:
$msGraphAccess = az account get-access-token --resource "https://graph.microsoft.com |
ConvertFrom-Json
$accessToken = $msGraphAccess.accessToken
$headers = New-Object 'System.Collections.Generic.Dictionary[String,String]'
$headers.Add("Content-Type", "application/json")
$headers.Add("Authorization", "Bearer " + $accessToken)

Azure Get Authorization Bearer Token API

I'm just wondering in this article https://learn.microsoft.com/en-us/rest/api/resources/tenants/list
there's a "try it" button once you click it, it will list all your tenant or directory.
then once you select any of the directory it will give you a bearer token.
.
The question is, is there's a way to get a bearer token thru API? Or get a bearer token that depends on the selected tenant? Thanks!
By the return token of that site, im passing it thru this api https://app.vssps.visualstudio.com/_apis/accounts to get all my organization base on the selected tenant.
If you want to work with the command in PowerShell, the Get-AzAccessToken cmdlet can fetch a token for you.
I tested the following script in PowerShell on Azure Cloud Shell:
$token = (Get-AzAccessToken -ResourceUrl 'https://management.azure.com').Token
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization","Bearer $token")
$url = "https://management.azure.com/tenants?api-version=2020-01-01"
# Send the request
Invoke-RestMethod $url -Method 'Get' -Headers $headers
You can get the access token (Bearer) via below API. Please refer the link.
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
Normally if you need to access any azure resource, then you have to create AAD app in that tenant in order to get the token. But your case, you have to get all Tenant details via REST api. So You can create the AAD app on of your tenant.

Azure REST access token

I want next:
From my website to be able to start virtual server (Ubuntu, linux, windows server).
I dit this with AWS and there was simple to find via IAM the access key and token.
I would like to do the same if possible with Azure, to get the access key and token. I found some tutorials on how to like here: https://www.youtube.com/watch?v=ujzrq8Fg9Gc&t=51s but it makes so much things and I just need key token and secret token to be able to access the virtual hosts and manipulate it.
I see there is also oAuth2 and tha is too much to set it up for this project.
there is also so called azure ad https://learn.microsoft.com/en-us/rest/api/
So any help would be nice to find that easy access key key and token to list, create, update virtual machines.
Maybe because I have free account?
Update:
I found this one and it is very easy:
https://learn.microsoft.com/en-us/rest/api/compute/virtualmachines/createorupdate
just say: PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}?api-version=2017-12-01
subscriptionID if I provide this, would that be enough?
I was thinking there should be some authorization?
As Thuan Ng said, you need get token firstly. If you want to get the token, you need create a service principal and give it Owner role. More information please check this link.
After the sp is created, you will get client id, client secret. You could use them to get token. More information you could get the link. For power shell to get token, you could use the following example:
##get token
$TENANTID=""
$APPID=""
$PASSWORD=""
$result=Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body #{"grant_type" = "client_credentials"; "resource" = "https://management.core.windows.net/"; "client_id" = "$APPID"; "client_secret" = "$PASSWORD" }
$token=$result.access_token
##set subscriptionId and resource group name
$subscriptionId=""
$resourcegroupname="shui5"
$Headers=#{
'authorization'="Bearer $token"
'host'="management.azure.com"
'contentype'='application/json'
}
$body='{
"location": "northeurope",
"tags": {
"tagname1": "test-tag"
}
}'
Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/$subscriptionId/resourcegroups/${resourcegroupname}?api-version=2015-01-01" -Headers $Headers -Method PUT -Body $body
For postman:
After you get the token, you could call rest API. For example:
To be authorized by Azure AD Authorization server, you need to get access token first. The URI (PUT) is not enough. To get access token, normally you need to go to Azure AD to register your client app (it is kind of object to be used for authorization, not an app in Apple or Android store you might think). When registering app, you are given client ID and can generate a client secret. With tenant ID, client ID and client secret, you can use HTTP Request to request access token from the OAuth2 endpoint https://login.microsoftonline.com/{tenantID}/oauth2/token. After you have access token, you need to construct authorization header in your Http request. It's Bearer token.
When using PUT, you also need to construct the request body object. Here is an example
var requestBody = new
{
location = westus,
properties = new
{
hardwareProfile = new
{
vmSize = "Standard_D1_v2"
},
storageProfile = new
{
osDisk = new
{
name = "VMDisk",
image = new
{
uri = ...
}
}
}
....
};
The request body doesn't have to be anonymous type like the one I defined above. That depends on your familiarity. If using such a structure, you can use PutAsJsonAsync(url, requestBody) . Url is actually the request Url which is the combination of Uri (management.azure.com) and the parameter {subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}?api-version=2017-12-01
I detailed the access token with Http Request here http://thuansoldier.net/?p=6790
And if you want to know more details about how to use PUT to request to Azure Resource Manager API, here is the detail http://thuansoldier.net/?p=7292 (looking up the heading Creating a new key vault in which I described how to use PUT and to construct request body) This is exactly what you'd need to create a new VM resource.

Resources