Related
I'm trying to get all Graph API permissions list by an API call or by downloading either XML or JSON file.
I tried to check call made from Azure portal when list is loaded but nothing.
Does someone know how we can get this info from Microsoft?
Api permissions can be listed by using following query in microsoft graph api.Microsoft graph explorer
Directory.Read.All permission is required to be granted admin consent authenticate a Microsoft Graph API client to access the /v1.0/oauth2PermissionGrants endpoint.
Then make a GET request to
https://graph.microsoft.com/v1.0/oauth2PermissionGrants
Result: Represents delegated permissions which have been granted for client applications to access APIs on behalf of signed-in users.
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#oauth2PermissionGrants",
"#odata.nextLink": "https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$skiptoken=xxxx",
"value": [
{
"clientId": "xxx",
"consentType": "Principal",
"id": "YBLh22Q2xxxxxxZPqphjW",
"principalId": "xxxx",
"resourceId": "xxxxxx",
"scope": "UserProfile.Read "
},
{
"clientId": "xxxx",
"consentType": "Principal",
"id": "xxxx",
"principalId": "xxxx6efe7a",
"resourceId": "xxxxx",
"scope": "UserProfile.Read "
},
{
"clientId": "xxxx",
"consentType": "Principal",
"id": "YBLh2xxxxxmX",
"principalId": "xxxxxxx",
"resourceId": "xxxx",
"scope": "UserProfile.Read "
},
{
"clientId": "xxxxx",
"consentType": "Principal",
"id": "YBLh22Q2xxxxxxN2iXWD",
"principalId": "xxxxx",
"resourceId": "xxxx",
"scope": "UserProfile.Read"
},
{
"clientId": "xxxxx",
"consentType": "Principal",
"id": "YBLh22Q2xExxxxbjbxXaqHKDW",
"principalId": "xxxx",
"resourceId": "xxxxx",
"scope": "UserProfile.Read"
},
{
"clientId": "xxxxxxx",
"consentType": "Principal",
"id": "xxxxxxxx",
"principalId": "xxx",
"resourceId": "bbf1c2f4xxxxxxxx",
"scope": "user_impersonation "
},
{
"clientId": "xxxx-60ae65bca24f",
"consentType": "Principal",
"id": "xxxx_AXxTLAO2AAHbv56",
"principalId": "941ea60dxxxxxx-d800076efe7a",
"resourceId": "bbf1c2f4xxxxx",
"scope": "user_impersonation "
},
{
"clientId": "xxxx9-60ae65bca24f",
"consentType": "Principal",
"id": "xxx",
"principalId": "xxx",
"resourceId": "bbf1c2f4-xxxxx",
"scope": "user_impersonation"
},
{
"clientId": "dbe11260-3664-40c4-ae39-60ae65bca24f",
"consentType": "Principal",
"id": "xxxx",
"principalId": "d1de0f56-d471-4580-b8db-c576aa1ca0d6",
"resourceId": "bbf1c2f4-52df-4d28-8dea-e8de231ed902",
"scope": "user_impersonation"
}
Reference: List oAuth2PermissionGrants (delegated permission grants) - Microsoft Graph v1.0 | Microsoft Learn
thanks for answers but it's not exactly what i was seeking about.
In fact, i want to get list we can find here Graph api permissions
but throught an automatic way (Api, Json or Xml file and not by parsing an Html page :). Idealy with extra info if existing to let my users filter them easily
AFAIK there is no list by an api call or by downloading XML or JSon file available right now, if you want this API , you can raise a feature request here.
Check the documentation of all permissions and ids. You can easily copy and paste the table.
Other option is to use /servicePrincipals endpoint and filter Microsoft Graph app. It will return list of application and delegated permissions including description and other details.
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId+eq+'00000003-0000-0000-c000-000000000000'&$select=appRoles,oauth2PermissionScopes
Result
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals(appRoles,oauth2PermissionScopes)",
"value": [
{
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Allows the app to read all available Teams Templates, without a signed-user.",
"displayName": "Read all available Teams Templates",
"id": "6323133e-1f6e-46d4-9372-ac33a0870636",
"isEnabled": true,
"origin": "Application",
"value": "TeamTemplates.Read.All"
},
...
],
"oauth2PermissionScopes": [
{
"adminConsentDescription": "Allows the app to read the available Teams templates, on behalf of the signed-in user.",
"adminConsentDisplayName": "Read available Teams templates",
"id": "cd87405c-5792-4f15-92f7-debc0db6d1d6",
"isEnabled": true,
"type": "User",
"userConsentDescription": "Read available Teams templates, on your behalf.",
"userConsentDisplayName": "Read available Teams templates",
"value": "TeamTemplates.Read"
},
...
]
}
]
}
appRoles property represents application permissions
oauth2PermissionScopes property represents delegated permissions
The endpoint requires Application.Read.All, Application.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All permissions
I've compared data returned by the query above with the list in the documentation and it matches.
I'm creating a Java application which create a call between participants.
According to the documentation (https://learn.microsoft.com/en-us/microsoftteams/platform/bots/calls-and-meetings/registering-calling-bot) I already create a Microsoft bot and added MsTeams channel. In the Azure portal I create an App registration with required permissions and when I call a POST https://graph.microsoft.com/v1.0/communications/calls I got an error
POST https://graph.microsoft.com/v1.0/communications/calls
SdkVersion : graph-java/v5.13.0
SdkVersion : graph-java/v5.13.0
{
"callbackUri":"CALLBACK_URL",
"direction":"outgoing",
"mediaConfig":{"blob":""},
"mediaState":{"audio":"active"},
"meetingInfo":{
"organizer":{
"user":{
"displayName":"User 2",
"id":"63678056-8b5a-47e4-8688-dc77b73ff439"
}
}
},
"requestedModalities":["audio"],
"source":{
"identity":{
"user":{
"displayName":"User 2",
"id":"63678056-8b5a-47e4-8688-dc77b73ff439"
}
}
},
"targets":[
{
"identity":{
"user":{
"displayName":"User 1",
"id":"a65a4c0b-9174-4166-b8d2-825822b4822b"
}
}
}
],
"tenantId":"8a61bdf8-xxxx"}
500 : Internal Server Error
client-request-id : 15893b89-16a4-4bef-9d5b-9f358c13bee1
Content-Type : application/json
Date : Tue, 15 Mar 2022 16:37:57 GMT
request-id : 1840d2a7-7b98-4206-8c2e-46a57017f67c
Strict-Transport-Security : max-age=31536000
Transfer-Encoding : chunked
Vary : Accept-Encoding
x-ms-ags-diagnostic : {"ServerInfo":{"DataCenter":"West Europe","Slice":"E","Ring":"5","ScaleUnit":"001","RoleInstance":"AM4PEPF000157B4"}}
{
"error": {
"code": "9999",
"message": "Unknown internal server error.",
"innerError": {
"date": "2022-03-15T16:37:57",
"request-id": "1840d2a7-7b98-4206-8c2e-46a57017f67c",
"client-request-id": "15893b89-16a4-4bef-9d5b-9f358c13bee1"
}
}
}
Example of the accessToken
{
"typ": "JWT",
"nonce": "bA2X57jOLNLhtgSE1ymo2U_ap9IOV_tmxjuMQ5-LQpQ",
"alg": "RS256",
"x5t": "jS1Xo1OWDj_52vbwGNgvQO2VzMc",
"kid": "jS1Xo1OWDj_52vbwGNgvQO2VzMc"
}.{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/8a61bdf8-1b33-4b6d-a95f-f99546e97f08/",
"iat": 1647361546,
"nbf": 1647361546,
"exp": 1647365446,
"aio": "E2ZgYHjGFc69hKdaxufkZIVLP7dsAQA=",
"app_displayname": "ms-teams-test-call-app",
"appid": "d04b6155-xxxx",
"appidacr": "1",
"idp": "https://sts.windows.net/8a61bdf8-1b33-4b6d-a95f-f99546e97f08/",
"idtyp": "app",
"oid": "1f18bac4-xxxx",
"rh": "0.AVAA-L1hijMbbUupX_mVRul_CAMAAAAAAAAAwAAAAAAAAAB_AAA.",
"roles": [
"Calls.JoinGroupCall.All",
"Calls.InitiateGroupCall.All",
"Calls.JoinGroupCallAsGuest.All",
"Calls.AccessMedia.All",
"Calls.Initiate.All"
],
"sub": "1f18bac4-a630-42fe-bca2-7acffb476ee6",
"tenant_region_scope": "NA",
"tid": "8a61bdf8-xxxx",
"uti": "xiwA4EWhSU6hdfviSQ_HAA",
"ver": "1.0",
"wids": [
"0997a1d0-0d1d-4acb-b408-d5ca73121e90"
],
"xms_tcdt": 1642728719
}.[Signature]
And one more - I can't find what information what I should set to the mediaConfig.blob if I'm using AppHostedMediaConfig?
The setup is as follows:
SPA web app that connects to a backend API. It's supposed to log in the user, request an access_token to the API and use it on all requests. Call it the Application.
Backend API that is supposed to receive access_tokens and authorise users based on the groups claim contained in it. Call it the API.
Configuration on the side of Azure AD:
The Application has redirect uris configured and is given an API permission to the API (the API.User scope).
The Backend exposes the API.User scope and authorises The Application as an Authorized client app.
Now, to get the groups claim I've added it to token configuration in both apps. Since it didn't work, I went and added some more optional claims to see if any of them are returned. They're not. The relevant parts of the manifest look like this:
"groupMembershipClaims": "All",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"optionalClaims": {
"idToken": [
{
"name": "email",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "nickname",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "given_name",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"accessToken": [
{
"name": "email",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "nickname",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "given_name",
"source": null,
"essential": false,
"additionalProperties": []
}
],
"saml2Token": [
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": []
}
]
}
Both app registrations are configured the same (with respect to the above values).
The frontend code retrieving the token:
msalInstance = new Msal.UserAgentApplication(
{
auth: {
clientId: <the Application's client id>
}
}
);
this.msalInstance.handleRedirectCallback((error, response) => {
console.warn("In handleRedirectCallback");
console.warn(JSON.stringify(error));
console.warn(JSON.stringify(response));
});
if (this.msalInstance.getAccount()) {
const request = {
scopes: ['api://<the API client id>/API.User']
}
this.msalInstance.acquireTokenSilent(request)
.then(response => {
console.warn("In acquireTokenSilent then");
console.warn(JSON.stringify(response));
})
.catch(err => {
if (err.name === 'InteractionRequiredAuthError') {
return this.msalInstance.acquireTokenRedirect(request);
}
});
}
else {
const request = {
scopes: ['user.read', 'email', 'openid', 'profile']
};
this.msalInstance.loginRedirect(request);
}
I am clearly doing something wrong, as all access_tokens and id_tokens have the same layout completely independent of any changes I make to the app registrations or the request.scopes. I see that the MSAL request has a claimsRequest field, but it's undocumented and I don't know what should be put there. The MSDN docs make it sound as if all I needed to do was configure the app registration and the claims would be appended to the retrieved tokens, but it's clearly not the case.
Is there something else I have to configure to get the groups claim?
EDIT:
Example id_token layout that I'm getting:
{
"aud": "api://<the Application client id>",
"iss": "https://login.microsoftonline.com/<the Tenant id>/",
"iat": 1585052362,
"nbf": 1585052362,
"exp": 1585056262,
"aio": <Azure AD opaque string>,
"given_name": "<My first name>",
"hasgroups": "true",
"name": "<My account name>",
"nonce": <some guid>,
"oid": "<my account OID>",
"preferred_username": "<my email>",
"sub": <...>,
"tid": "<the tenant id>",
"uti": <Azure AD opaque string>,
"ver": "2.0"
}
example access_token I'm getting:
{
"aud": "api://<the Application client id>",
"iss": "https://sts.windows.net/<the Tenant id>/",
"iat": 1585052365,
"nbf": 1585052365,
"exp": 1585056265,
"acr": "1",
"aio": <Azure AD opaque string>,
"appid": "<the Application client id>",
"appidacr": "0",
"family_name": <my last name>,
"given_name": <my first name>,
"hasgroups": "true",
"ipaddr": <my ip addr>,
"name": <my account name>,
"oid": <my account oid>,
"onprem_sid": <not sure what this is, but some identifier>,
"scp": "API.User",
"sub": <...>,
"tid": <the tenant ID>,
"unique_name": <my email>,
"upn": <my email>,
"uti": <Azure AD opaque string>,
"ver": "1.0"
}
Since you commented that you are getting the hasgroups claim, it means the groups were not included in the token for most likely, size restrictions.
The claim is documented here: https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens.
Relevant quote from there:
If present, always true, denoting the user is in at least one group. Used in place of the groups claim for JWTs in implicit grant flows if the full groups claim would extend the URI fragment beyond the URL length limits (currently 6 or more groups)
So 5 is the maximum in implicit flow.
The 200 maximum is for e.g. authorization code flow.
Our code started throwing the following error today, for a very simple findMeetingTimes request.
This is the error:
{
"error": {
"code": "UnknownError",
"message": "{\"ClassName\":\"System.ArgumentNullException\",\"Message\":\"Value cannot be null.\",\"Data\":null,\"InnerException\":null,\"HelpURL\":null,\"StackTraceString\":\" at System.String.Join(String separator, String[] value)\\r\\n at Microsoft.Griffin.WebService.Calendar.Scheduling.DefaultController.<ExecuteWorkflow>d__53`2.MoveNext()\",\"RemoteStackTraceString\":null,\"RemoteStackIndex\":0,\"ExceptionMethod\":\"8\\nJoin\\nmscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\\nSystem.String\\nSystem.String Join(System.String, System.String[])\",\"HResult\":-2147467261,\"Source\":\"mscorlib\",\"WatsonBuckets\":null,\"ParamName\":\"value\"}",
"innerError": {
"request-id": "f9153038-b8e2-41a8-bba6-dad2a8cc3afa",
"date": "2019-09-10T12:01:37"
}
}
This is the POST request
{
"attendees": [{
"emailAddress": {
"address": "amy#domain.com"
},
"type": "required"
}],
"timeConstraint": {
"timeslots": [{
"start": {
"dateTime": "2019-09-10T12:01:36",
"timeZone": "UTC"
},
"end": {
"dateTime": "2019-09-17T12:01:36",
"timeZone": "UTC"
}
}]
},
"meetingDuration": "PT30M",
"maxCandidates": 4,
"minimumAttendeePercentage": 100
}
Anyone got an idea what might be causing this?
// Edit:
Some more testing revealed that this is still working with a bearer token from Microsoft Graph Explorer, but not our own token which generated from an AzureAD app registration. From what we understand the tokens should be both valid (and have been up until a few hours ago... Our token also works for other endpoints)
Our token data:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/0e7219f7-4c4d-47e7-b98a-7b9b9de02b80/",
"iat": 1568152509,
"nbf": 1568152509,
"exp": 1568156409,
"acct": 0,
"acr": "1",
"aio": "******",
"amr": [
"pwd",
"mfa"
],
"app_displayname": "Outlook Meetings for Jira",
"appid": "fb930189-fe2c-4b11-b424-f576f7b371b3",
"appidacr": "1",
"family_name": "*******",
"given_name": "*****",
"ipaddr": "185.85.64.210",
"name": "*****",
"oid": "12ad9a79-78ae-424a-b6ef-a6ec78f69f3f",
"platf": "3",
"puid": "10033FFF8670ACD2",
"scp": "Calendars.ReadWrite.Shared email offline_access User.Read User.ReadBasic.All",
"signin_state": [
"kmsi"
],
"sub": "QsD80H0dBCYK4wttPZFIY1w_Pi5Ygbn9OwKuiNkNPXo",
"tid": "0e7219f7-4c4d-****-b98a-7b9b9de02b80",
"unique_name": "...#....com",
"upn": "...#....com",
"uti": "uzKz01rSV0SD1kTwBZJkAA",
"ver": "1.0",
"wids": [
"62e90394-69f5-4237-9190-012177145e10"
],
"xms_tcdt": 1374053072
}
Is it possible to get a list of scopes from an access token?
e.g.
$token = 'ab12..'
$scopes = tokenToScopes($token)
// --> $scopes = ['address', 'subscriptions',...]
That can depend upon the access token. If its a Jwt you can just decode it you can test it by using using jwt.io. A lot of auth servers also have a tokeninfo endpoint which will give you information on your token. This will depend upon the auth server you are using.
{
"nbf": 1514888070,
"exp": 1514891670,
"iss": "http://localhost:5000",
"aud": [
"http://localhost:5000/resources",
"testapi"
],
"client_id": "testclient",
"sub": "21248582",
"auth_time": 1514882023,
"idp": "Google",
"supporter": "21248582",
"name": "Xxxxx",
"application_id": "14055160",
"scope": [
"openid",
"profile",
"email",
"testapi"
],
"amr": [
"external"
]
}