Can I add a custom static claim to auth tokens with a AAD OIDC app registration? - azure-active-directory

I have a basic Azure AD App Registration. This is a non-interactive client IE console/machine client with a secret and no redirect URI. I would also like this to also work for interactive clients however.
How can I add a claim to my token called "hello": "world"?

To add a custom claim like "hello": "world" in the token, you can create claim mapping policy using PowerShell.
1)Make sure to have AzureADPreview module installed, before running below commands.
Connect-AzureAD
New-AzureADPolicy -Definition #('
{
"ClaimsMappingPolicy":
{
"Version":1,"IncludeBasicClaimSet":"true",
"ClaimsSchema": [{"Source":"user","ID":"extensionattribute1","SamlClaimType":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hello","JwtClaimType":"hello"}]
}
}') -DisplayName "HelloExtraClaim" -Type "ClaimsMappingPolicy"
Output:
2)Note the ID of the policy and assign it to your service principal using below command:
Add-AzureADServicePrincipalPolicy -Id serviceprincipal_ObjectID -RefObjectId policy_ID
3)To confirm whether the policy is assigned or not, run below command:
Get-AzureADServicePrincipalPolicy -Id serviceprincipal_ObjectID
Output:
4)To assign value to that claim, sign in as admin to Microsoft Graph Explorer and run the below query:
PATCH https://graph.microsoft.com/beta/me
{
"onPremisesExtensionAttributes":
{
"extensionAttribute1": "world"
}
}
Response:
5)Make sure to set "acceptMappedClaims": true in App's Manifest like below:
Go to Azure Portal -> Azure Active Directory -> App registrations -> Your App -> Manifest
6)Go to Expose an API tab and set Application ID URI to your domain like below:
7)Generate a token to your application by signing with admin account.
After decoding the above ID token in jwt.ms, I got the claim "hello": "world" successfully as below:
Credits: How to add custom user defined claims to azure ad token | GitHub by TiagoBrenck

Related

How to use Terraform `google_app_engine_domain_mapping` with service account?

I'm trying to create a GCP App Engine domain mapping via Terraform with the following configuration:
provider "google" {
version = "3.36.0"
region = var.region
}
resource "google_app_engine_domain_mapping" "domain_mapping" {
project = local.project_id
domain_name = var.domain_name
ssl_settings {
ssl_management_type = "AUTOMATIC"
}
depends_on = [
google_app_engine_application.backend_app
]
}
Terraform is configured to use an organization level service account for the GCP provider with the following IAM permissions (no conditions):
Billing Account User
Project Creator
Service Config Editor (I've added this thinking it would resolve the issue based on this and this doc page.)
The Google account that is the owner of the organization has verified the domain in question, yet I'm getting the following error:
Error: Error creating DomainMapping: googleapi: Error 403: Caller is not authorized to administer the domain 'testing.redacted.com'. If you own 'testing.redacted.com', you can obtain authorization by verifying ownership of the domain, or any of its parent domains, via the Webmaster Central portal: https://www.google.com/webmasters/verification/verification?domain=testing.redacted.com. We recommend verifying ownership of the largest scope you wish to use with subdomains (eg. verify 'example.com' if you wish to map 'subdomain.example.com').
I've also tried adding the service account's email as a user in the Google Search Console to the domain to no avail.
The solution is rather simple but sort of hidden in the docs. You need to add your service account email as owner of the domain.
Go here
Select the property you want
Tap the "Add an owner" button at the bottom of the page and add the email address (e.g. terraform#<PROJECT_ID>.iam.gserviceaccount.com)

Does what you send in Scope Governs whether you can login with Microsoft Account using Azure AD V2 Endpoints

I have registered a application using the App Registration (Preview) Blade and added the Azure Service Management API as API Permissions I downloaded the MSAL based Sample from
https://github.com/azure-samples/active-directory-dotnet-webapp-openidconnect-v2
Now in startup.auth.cs if i change the Scope i.e keep openid and add https://management.azure.com and then run and try and Login with a Microsoft Account i get the following error
This Doesn't Look like a Work or School Email you cant Sign-in here with Personal Account use your work or School Account Instead.
if i remove the Scope for https://managment.azure.com and just keep Openid profile offline_access i get the Consent Screen and Login
new OpenIdConnectAuthenticationOptions
{
// The Authority represents the v2.0 endpoint - https://login.microsoftonline.com/common/v2.0
// The Scope describes the initial permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
ClientId = clientId,
Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, "common", "/v2.0"),
RedirectUri = redirectUri,
Scope = "openid https://management.azure.com/.default",
PostLogoutRedirectUri = redirectUri,
I am Expecting to have the user Login and Obtain a Token for management API , i am Looking for Reasons for getting the above Error is this Expected ? The Account that i am using exists in my directory as a Member . this works if i use a Managed user(user#tenant.onmicrosoft.com) to Login
Since personal MS accounts cannot be used to manage Azure subscriptions unless they are added to an Azure AD, you should use the organizations endpoint instead of common.
In v1 "common" meant any AAD tenant.
In v2 "common" means any AAD tenant + any personal MS account.
If you wanted only personal accounts, you can use "consumers".
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc#fetch-the-openid-connect-metadata-document
You can use "organizations" to allow any AAD tenant but disallow MS accounts.
Of course a user can just edit the URL and login with a personal MS account anyway, so you'll want to check the tenant id of the logged in user.
The tenant id for MS accounts is always 9188040d-6c67-4c5b-b112-36a304b66dad, per the docs: https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens#payload-claims.
So check the idp claim.

Grant service principal access to application in other tenant

I have an Azure AD service principal in one tenant (OneTenant) that I would like to give access to an application in another tenant (OtherTenant).
The service principal in tenant OneTenant is a managed service identity for an Azure Logic App. So what I actually want is to call an API from my Logic App. This API is protected by an Azure AD application in OtherTenant.
The application in OtherTenant defines a number of roles and the service principal in OneTenant should have one of these roles so it can call the API.
I tried the following:
set the app in OtherTenant to multi-tenant
ran the following PS command to attempt to add the SP to a role in the app:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
(both logged in in OneTenant and OtherTenant)
This gives an error stating that either app-id-in-other-tenant or object-id-of-sp-in-one-tenant can not be found, depending on where I am signed in.
I also tried creating a Service Principal in OneTenant based on the app-id from OtherTenant In that case I get an error message: Authenticating principal does not have permission to instantiate multi-tenantapplications and there is not matching Applicationin the request tenant.
Ok, I finally got around to testing if the solution presented by Rohit Saigal works. It does point in the right direction but is not complete.
First step is to create a service principal in OneTenant that represents the application in OtherTenant. So while signed in to OneTenant, run the following script:
$spInOneTenant = New-AzureADServicePrincipal -AppId <app-id-in-other-tenant>
Next step is to run the New-AzureADServiceAppRoleAssignment cmdlet with the following parameters:
New-AzureADServiceAppRoleAssignment `
-Id <role-id> `
-ObjectId <object-id-of-sp-in-one-tenant> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId $spInOneTenant.ObjectId
The trick is to use the object id of the service principal you created in the previous step as the ResourceId.
Taking the command as is from your question:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
Try changing the last parameter value i.e. ResourceId
Currently you're passing <app-id-in-other-tenant>
Replace that with <object-id-of-API-in-other-tenant>
The question/answers presented here were helpful, but yet it took me some time to work through the details and actually make it work, so allow me to elaborate some more on the above, as it might help others too.
Scenario
Two tenants:
Home Tenant.
Other Tenant.
One Azure App Service API app, with access managed by the Home Tenant.
One Logic app placed in a subscription in Other Tenant that need to securely access the API app in the Home Tenant.
Approach
Application registration
For the API app to delegate identity and access management to Azure AD an application is registered in the home tenant’s Azure Active Directory. The application is registered as a multi-tenant app.
You also need to create an app role (see documentation: How to: Add app roles in your application and receive them in the token), lets call it read.weather.
Configuration of Other Tenant and Logic App
To provide the Logic App access to the API app do this:
Enable a system assigned identity for the logic app - i.e. use Managed Identity. Note down the system assigned managed identity Object ID ({18a…}), you will need it in a minute.
Create a service principal for the application in the Other Tenant using this command, where appId is the appId of the application registered in Home Tenant (e.g. lets say it’s {1a3} here):
New-AzureADServicePrincipal -AppId {appId}
This command will output a json document which includes among other things an objectId for the service principal just created.
[... more json ...]
"objectId": "b08{…}",
[... more json...]
You should also see the appRoles, including the app role read.weather you just created, om the json output from the New-AzureADServicePrincipal command:
[... more json...]
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Read the weather.",
"displayName": "Read Weather",
"id": "46f{…}",
"isEnabled": true,
"value": "read.weather"
}
],
[... more json...]
To tie it all together make an app role assignment using the command:
New-AzureADServiceAppRoleAssignment -Id {app role ide} -ObjectId {system assigned identity object id} -PrincipalId {system assigned identity object id} -ResourceId {object id of service principal}
E.g. something like this:
New-AzureADServiceAppRoleAssignment -Id 46f… -ObjectId 18a… -PrincipalId 18a… -ResourceId b08…
Now we are ready to set up the HTTP request in the Logic App using the URI to the API app using Managed Identity for authentication.
Notice that the audience is needed and has the form: api://{appId}.
But wait…!
Does this mean that anyone could do this, if only they know the appId of your application registration, and wouldn’t this compromise the security of the API app?
Yes, it does, and yes indeed it could compromise the security of the API app.
If you look at the access token being created and used as bearer from the Logic App it is a valid access token, which contains all the necessary claims, including the app role(s). The access token is however issued by Other Tenant and not Home Tenant.
Therefore, if you have a multi tenanted application and you want to guard it against this scenario, then you could check the issuer (tid more likely) of the incoming access token calling the API and only accept it if the issuer is the Home Tenant, or you could make the application a single tenant app.
Or, you could require that the issuer matches a list of tenants that the API trusts.

Adding users with roles into app registration

I can see you can create app registrations with graph API but is it possible to add users and roles to an app registration?
If you want to assign a user to that application, in one of the specified app roles, you'll need to set the appRoleAssignment on the user . If using Azure AD Graph api , you could use below rest api :
https://graph.windows.net/{tenant-id}/users/{username}/appRoleAssignments?api-version={api-version}
Content-Type:application/json
Authorization: Bearer {token}
{
"id": "RoleID",
"principalId": "UserObjectID",
"principalType": "User",
"resourceId": "servicePrincipalID"
}
id: This is the Id for the Role you are assigning. These Ids can be found in the Application's Manifest. Or you could use below api to get the specific role defined for your application(appRoles claim):
https://graph.windows.net/{tenant}/applications/{ObjectIDOfApplication}?api-version=1.6
principalId :This is the Obeject Id of the User you are assigning the role to.
principalType :If you are assigning this role to a User then this is set to the string User .
resourceId : Service Principal ID of the application . To get service principal id , you could use below api (objectId claim) :
https://graph.windows.net/{tenant}/servicePrincipals?api-version=1.6&$filter=appId eq 'appid'
Application role assignments are available in the Microsoft Graph Beta endpoint: see Update approleassignment
To give you an idea of what could do to add app role assignments to a user, I suggest you look at the Configure.ps1 PowerShell script of the active-directory-dotnet-webapp-roleclaims sample on GitHub, which creates test users of a given role and updates the application registration. This is in PowerShell, but you should be able to adapt it to using MSGraph

How to programatically create applications in Azure AD

I'm currently creating my applications on Azure Active directory manually whenever there is a request for a new environment. I was exploring ways to create these applications from the code via REST API. I had success in creating users and groups on existing applications by using 'client_credentials' as shown.
ClientCredential clientCred = new ClientCredential(clientID, clientSecret);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(resAzureGraphAPI, clientCred);
In similar fashion I tried to use the 'access_token' generated from above to create a new application
adClient.Applications.AddApplicationAsync(newApplication).Wait()
But this throws an error- "Insufficient privileges to complete the operation."
I looked at other threads and the Azure AD msdn page and turns out the client_credentials flow does not support creating/updating applications.
Adding Applications programmatically in Azure AD using Client Credentials Flow
The above thread also mentioned that way to workaround it was by using the 'grant_type=password' flow. I tried it as suggested but I keep getting the following error which doesn't make sense to me.
"error": "invalid_grant",
"error_description": "AADSTS50034: To sign into this application the account must be added to the 1283y812-2u3u-u293u91-u293u1 directory.\r\nTrace ID: 66da9cf9-603f-4f4e-817a-cd4774619631\r\nCorrelation ID: 7990c26f-b8ef-4054-9c0b-a346aa7b5035\r\nTimestamp: 2016-02-21 23:36:52Z",
"error_codes": [
50034
],
Here is the payload and the endpoint that I'm hitting. The user that is passed is the owner of the AD where I want to create the application
endpoint:https://login.windows.net/mytenantID/oauth2/token
post data
resource 00000002-0000-0000-c000-000000000000
client_id id
client_secret secret
grant_type password
username principal#mydomain.com
password password
scope openid
Any thoughts or suggestions of where I might be going wrong would be appreciated.
You can use PowerShell to create your apps:
$servicePrincipalName =”Your Client App Name”
$sp = New-MsolServicePrincipal -ServicePrincipalNames $servicePrincipalName -DisplayName $servicePrincipalName -AppPrincipalId “Your Client ID"
New-MsolServicePrincipalCredential -ObjectId $sp.ObjectId -Type Password -Value “Your client secret”
Add-MsolRoleMember -RoleObjectId “62e90394-69f5-4237-9190-012177145e10" -RoleMemberType ServicePrincipal -RoleMemberObjectId $sp.ObjectId
The role denoted by 62e90394-69f5-4237-9190-012177145e10 is the Admin role, and this can be adjusted as required to the ObjectId of any other role. Run Get-MsolRole to get a list of roles and ObjectIds.
You could then run this code from your App or run it manually. You will also need to run your connection code before the above, something along the lines of:
$loginAsUserName = "Your Tenancy Admin Account"
$loginAsPassword = "Your Tenancy Admin Account Password"
$secpasswd = ConvertTo-SecureString $loginAsPassword -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ($loginAsUserName, $secpasswd)
Connect-MsolService -Credential $creds
I was able to create the application in my tenant. The AD tenant which I was using to create the application under was verified for a different domain. Basically I ended up plugging in an user from that domain and using the resource_type=password flow was able to generate an access token. Next, firing the following lines of code did the trick
ActiveDirectoryClient adClient = new ActiveDirectoryClient(
serviceRoot,
AccessToken);
adClient.Applications.AddApplicationAsync(newApplication).Wait();
Check the following things which seem to be a little off in your POST to the OAuth Token endpoint:
When wanting access to the Graph API of your Azure AD, you will need to pass https://graph.windows.net as the resource body parameter; this is (imho) not well documented, but that's what you need to do
As client_id and client_secret you need to pass the Client ID and the Key of a predefined Application inside your Azure AD which in turn you have granted permissions on a per user level to; these need to be sufficient to add applications
See here: https://msdn.microsoft.com/Library/Azure/Ad/Graph/howto/azure-ad-graph-api-permission-scopes?f=255&MSPPError=-2147217396
The scope parameter is not used, I think; you will get the claims you defined inside the Azure AD management portal back (the assigned permissions for your application)
This should render you an access token you can then subsequently use on the https://graph.windows.net/tenantId/ end points.

Resources