Введение в проблему
У меня есть два разных Azure AD B2C tenants
один для dev , а другой для production . Оба с двумя приложениями: приложение ROPC_AUTH и приложение API .
Оба клиента имеют ROP C User Flow.
Оба клиента имеют одинаковые subscription Id
и одинаковые Resource Group
.
Я использую эти клиенты для входа , регистрации (с использованием GraphAPI POST
) и Сбросить пароль (используя GraphAPI PATCH
).
Все работает нормально для Login и Registration настройки аутентификации и GraphAPI в моем бэкэнд. Однако Reset Password работает только для одной из моих конфигураций Tenant; Я получаю 403. Недостаточно прав для другого.
Конфигурации
Ниже приведены манифесты для двух приложений в обоих клиентах.
Манифест приложения API клиента 1
{
"id": "581c1a83-ff0c-49ed-8ace-aa5b63e9ea44",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": false,
"appId": "xxxxdf64-9136-4d2b-xxxx-e02ffxxxxe36",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-12-06T14:31:53Z",
"groupMembershipClaims": null,
"identifierUris": [
"https://domain-1.onmicrosoft.com/api"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "SameNameAPI",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "Read User Files",
"adminConsentDisplayName": "Read User Files",
"id": "38115032-56b3-xxxx-9d81-xxxx039xx73f",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": "Read User Files",
"userConsentDisplayName": "Read User Files",
"value": "Files.Read"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2020-12-11T20:10:26.76Z",
"keyId": "d08800f2-ef0b-490d-9905-44fa82c1eab3",
"startDate": "2019-12-11T20:10:40.672Z",
"value": null,
"createdOn": "2019-12-11T20:10:23.7962051Z",
"hint": "U9L",
"displayName": "clientCreator"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "domain-1.onmicrosoft.com",
"replyUrlsWithType": [],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
},
{
"id": "dc5007c0-2d7d-4c42-879c-2dab87571379",
"type": "Role"
},
{
"id": "656f6061-f9fe-4807-9708-6a2e0934df76",
"type": "Role"
},
{
"id": "1b0c317f-dd31-4305-9932-259a8b6e8099",
"type": "Role"
},
{
"id": "65319a09-a2be-469d-8782-f6b07debf789",
"type": "Role"
},
{
"id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
"type": "Role"
},
{
"id": "09850681-111b-4a89-9bed-3f2cae46d706",
"type": "Role"
},
{
"id": "df021288-bdef-4463-88db-98f22de89214",
"type": "Role"
},
{
"id": "741f803b-c850-494e-b5df-cde7c675a1ca",
"type": "Role"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "5778995a-e1bf-45b8-affa-663a9f3f4d04",
"type": "Role"
},
{
"id": "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175",
"type": "Role"
}
]
},
{
"resourceAppId": "xxxxdf64-9136-4d2b-xxxx-e02ffxxxxe36",
"resourceAccess": [
{
"id": "38115032-56b3-xxxx-9d81-xxxx039xx73f",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Манифест приложения Tenant 2 API
{
"id": "ebexxxx-xxxx-41aa-80d4-512xxxxxx3ff",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": false,
"appId": "e633f406-xxxx-4c7a-85af-xxxxxxxxx436",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-06-05T16:19:02Z",
"groupMembershipClaims": null,
"identifierUris": [
"https://domain-2.onmicrosoft.com/api"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "SameNameAPI",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "Read User Files",
"adminConsentDisplayName": "Read User Files",
"id": "7b95e412-c753-4611-xxxx-xxxxx7aa4d78",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": "Read User Files",
"userConsentDisplayName": "Read User Files",
"value": "Files.Read"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-31T03:00:00Z",
"keyId": "99df4466-e1e7-4279-9699-063efacfbed7",
"startDate": "2020-06-05T16:45:24.082Z",
"value": null,
"createdOn": "2020-06-05T16:45:25.2186779Z",
"hint": "9b_",
"displayName": "clientCreator"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "sgmembershipb2bdev.onmicrosoft.com",
"replyUrlsWithType": [],
"requiredResourceAccess": [
{
"resourceAppId": "e633f406-xxxx-4c7a-85af-xxxxxxxxx436",
"resourceAccess": [
{
"id": "7b95e412-c753-4611-xxxx-xxxxx7aa4d78",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
},
{
"id": "dc5007c0-2d7d-4c42-879c-2dab87571379",
"type": "Role"
},
{
"id": "656f6061-f9fe-4807-9708-6a2e0934df76",
"type": "Role"
},
{
"id": "1b0c317f-dd31-4305-9932-259a8b6e8099",
"type": "Role"
},
{
"id": "65319a09-a2be-469d-8782-f6b07debf789",
"type": "Role"
},
{
"id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
"type": "Role"
},
{
"id": "09850681-111b-4a89-9bed-3f2cae46d706",
"type": "Role"
},
{
"id": "df021288-bdef-4463-88db-98f22de89214",
"type": "Role"
},
{
"id": "741f803b-c850-494e-b5df-cde7c675a1ca",
"type": "Role"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "5778995a-e1bf-45b8-affa-663a9f3f4d04",
"type": "Role"
},
{
"id": "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175",
"type": "Role"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Манифест приложения Tenant 1 Auth
{
"id": "5a6e70fe-xxx-4687-b77c-xxxxxxxxx3cf",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": true,
"appId": "877fc335-xxxx-xxx-b175-xxxxxxxxxddb",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-12-09T13:09:50Z",
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "ropc_auth2",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "domain-1.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://login.microsoftonline.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "https://domain-1.b2clogin.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "urn:ietf:wg:oauth:2.0:oob",
"type": "InstalledClient"
}
],
"requiredResourceAccess": [],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Манифест приложения Tenant 2 Auth
{
"id": "7c3d8eeb-xxxx-xxxx-b901-xxxxxxxxxe07",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": true,
"appId": "26c414be-xxxx-xxxx-b55d-xxxxxxxxxc40",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-06-05T15:08:34Z",
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "ROPC_Auth_app",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "domain-2.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "urn:ietf:wg:oauth:2.0:oob",
"type": "InstalledClient"
},
{
"url": "https://domain-2.b2clogin.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "https://login.microsoftonline.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
}
],
"requiredResourceAccess": [],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Использование
Конфигурация клиента GraphAPI
// Startup.cs --> ConfigureServices
services.AddScoped<IB2CGraphClient>(provider =>
{
var conf = provider.GetService<IConfigurationRoot>();
var section = conf.GetSection("AzureAd");
B2CGraphClient client = new B2CGraphClient(section.GetValue<string>("ClientId"),
section.GetValue<string>("ClientSecret"), section.GetValue<string>("Domain"));
return client;
});
Метод пользовательского PATCH
// GraphClient.cs
private async Task<string> SendGraphPatchRequest(string api, string json)
{
AuthenticationResult result = await
authContext.AcquireTokenAsync(Globals.aadGraphResourceId, credential);
HttpClient http = new HttpClient();
string url = Globals.aadGraphEndpoint + tenant + api + "?" + Globals.aadGraphVersion;
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), URL);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await http.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
string error = await response.Content.ReadAsStringAsync();
object formatted = JsonConvert.DeserializeObject(error);
throw new WebException("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
}
return await response.Content.ReadAsStringAsync();
}
Я отладил эти строки кодов, и изменение конфигурации в приложении выполняется с помощью настроек. методы с правильной информацией о клиенте.
Запрос и ответ
Запрос с использованием клиента 1
{
Method: PATCH,
RequestUri: 'https://graph.windows.net/domain-1.onmicrosoft.com/users/35761bb2-8729-xxxx-xxxx-xxxxxxxxxfe9?api-version=1.6',
Version: 1.1,
Content: System.Net.Http.StringContent,
Headers:
{
Authorization: Bearer some_token
Request-Context: appId=cid-v1:d6b30135-xxxx-xxxx-b5e2-xxxxxxxxxacf
Request-Id: |fbde7acc88133b4ab15e1ca11cd1cb64.xxxxxxxxxx.
traceparent: 00-fbde7acc88133b4ab15e1caxxxxxcb64-a99xxxxx8cfb9e4c-00
Content-Type: application/json; charset=utf-8
Content-Length: 172
}}
Клиент полезной нагрузки токена 1
{
"aud": "https://graph.windows.net/",
"iss": "https://sts.windows.net/fa11ae53-fc0b-xxx-xxxx-xxxxxxxxx48a/",
"iat": 1592416988,
"nbf": 1592416988,
"exp": 1592420888,
"aio": "42dgYDDxxxxxx4Ut954+Lpope+noSwA=",
"appid": "d7fddf64-xxxx-4d2b-xxxx-xxxxxxxxxe36",
"appidacr": "1",
"idp": "https://sts.windows.net/fa11ae53-fc0b-xxxx-a575-xxxxxxxx48a/",
"oid": "b4eb0d70-2ad1-xxxx-a5a1-xxxxxxxxdfa",
"roles": [
"Directory.Read.All",
"Directory.ReadWrite.All"
],
"sub": "b4eb0d70-xxxx-4c37-xxxx-xxxxxxxxdfa",
"tenant_region_scope": "NA",
"tid": "fa11ae53-fc0b-xxxxx-xxxx-xxxxxxxx48a",
"uti": "xxxxxxxxxxxxxxxxbAA",
"ver": "1.0"
}
Ответ с использованием Теннант 1
{
StatusCode: 204,
ReasonPhrase: 'No Content',
Version: 1.1,
Content: System.Net.Http.HttpConnectionResponseContent,
Headers: {...}
}
Запрос с использованием арендатора 2
{
Method: PATCH,
RequestUri: 'https://graph.windows.net/domain-2.onmicrosoft.com/users/59ef7da0-xxxx-xxxx-8b05-xxxxxxxxxd13?api-version=1.6',
Version: 1.1,
Content: System.Net.Http.StringContent,
Headers:
{
Authorization: Bearer some_token
Request-Context: appId=cid-v1:d6b30135-b6ac-xxxx-b5e2-xxxxxxxxxacf
Request-Id: |8d281xxxxxxxxx4acef74298ec03dd1.79867ebb617a364c.
traceparent: 00-8d28xxxxxxxxb44acef74298ec03dd1-79867ebb617a364c-00
Content-Type: application/json; charset=utf-8
Content-Length: 172
}
}
Клиент полезной нагрузки токена 2
{
"aud": "https://graph.windows.net/",
"iss": "https://sts.windows.net/06b0c6f1-7524-xxxx-xxxx-xxxxxxxxx731/",
"iat": 1592418325,
"nbf": 1592418325,
"exp": 1592422225,
"aio": "42dgYGxxxxxxxxxx8C3BWc6r6fbAwA=",
"appid": "e633f406-xxxx-4c7a-xxxx-xxxxxxxxx436",
"appidacr": "1",
"idp": "https://sts.windows.net/06b0c6f1-7524-xxxx-88be-xxxxxxxx731/",
"oid": "12d9a685-6083-xxxx-xxxx-xxxxxxxx4db",
"roles": [
"Directory.Read.All",
"Directory.ReadWrite.All"
],
"sub": "12d9a685-xxxx-47e1-xxxx-xxxxxxxxx4db",
"tenant_region_scope": "NA",
"tid": "06b0c6f1-7524-xxxx-xxxx-xxxxxxxxx731",
"uti": "xxxxxxxxxxxxxxxuAA",
"ver": "1.0"
}
Ответный арендатор 2
{
StatusCode: 403,
ReasonPhrase: 'Forbidden',
Version: 1.1,
Content: System.Net.Http.HttpConnectionResponseContent,
Headers:
{
...
}
}
// Content
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
},
"requestId": "9adf43b9-xxxx-xxxx-a393-xxxxxxxxxd54",
"date": "2020-06-17T17:47:19"
}
}