Wanted: Help with Scopes in Sample App/API

Siegfried Heintze 1,906 Reputation points
2020-06-01T19:05:05.547+00:00

I got active-directory-b2c-dotnet-webapp-and-webapi working and then discovered that this was a .NET Framework example and not a .NET Core example (as I had assumed -- silly me for not noticing sooner).

Since this example contained the instructions for registering the API and defining read/write scopes, perhaps this was a worthwhile exercise anyway.

(1) What is the difference between a scope and a permission? Where should I read about these scopes?

So I am working on the example 4-2-B2C and I don't understand this file appsettings.json (specifically the "TodoListScope") and I don't see the instructions for registering the API or defining read/write scopes like there was for the .NET Framework example.

(2) So I see in step three for the first example active-directory-b2c-dotnet-webapp-and-webapi that we need to define write and read scopes as part of registering the WebAPI. Is this necessary for 4-2-B2C also? If so, do we call them just "read" and write" or do we call them "readScope" and "writeScope"?

(3) What am I supposed to specify for this TodoListScope in file appsettings.json ? I took some guesses (none worked, I received the errors below), here are two guesses:

"TodoListScope": "https://enterprisedemoorg.onmicrosoft.com/aadb2cWebAPICoreToDoListAppIDURI/read"
"TodoListScope": "https://enterprisedemoorg.onmicrosoft.com/aadb2cWebAPICoreToDoListAppIDURI/user_impersonation"

(3) So I can sign-in to the web site, but I cannot access the ToDoList service. I keep getting this error:

System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it.
   ---> System.Net.Sockets.SocketException (10061): No connection could be made because the target machine actively refused it.

I see the WebAPI console is telling me it is seeing it (I think this means I got the port right):

  info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
  Request starting HTTP/1.1 GET http://localhost:44332/api/todolist
  

I see that TodoListController.cs line 23 is being called. Can someone please explain this "AuthorizeForScopes" and why this is in the client? In the task service we have an "[Authorize(Policy = "ReadScope")]" at TodoListController.cs line 66. Why do we need both of these declarations?

Thu Jun 11 2020 Update:

I still have all my old questions above. Here is some of the things I have tried

(1) I forgot to mention I'm using a AADB2C tenant (enterprisedemoorg.onmicrosoft.com) with Facebook & Microsoft Identity providers and sign-up-sign-out flows that I have working with some other examples.

(2) I'm unclear about 4-2-B2C where it says "make sure DisplayName is checked in User attributes and application claims"... What do they mean by checking DisplayName? There is no check box. Under user attributes I see a row called "DisplayName". What do I need to check? Also: where is application claims? Is there a second Display name I am supposed to check?

(3) Previous examples referenced me to active-directory-b2c-dotnet-webapp-and-webapi where (see step 3) you are supposed to click on "Published Scopes". Since I could not find "Published Scopes" for my API (aadb2cWebAPICoreToDoList) I clicked on "Expose an API" and added three scopes:

Then I went to my Client (aadb2cWebAppCoreToDoList) Registration and clicked on "API Permissions" and added read, write & user_impersonation permissions. Since this is not in the tutorial instructions I am uncertain if this is correct. Should this be in the tutorial instructions?

Mon Jun 22 2020 Update:

Yes -- I finally found it documented in

"%SRCROOT%\4-WebApp-your-API\4-2-B2C\README-incremental-instructions.md(line 160)". I think this tidbit of information is missing from the online documentation of the project.

OK, I update "%SRCROOT%\4-WebApp-your-API\4-2-B2C\Client\appsettings.json(26)" accordingly with development mode turned on in both the client and the API.

Now when I go to https://localhost:5000 I get this error:

Error.
An error occurred while processing your request.
Request ID: |fb0c6077-4dfcae6f9f3ccc15.

Development Mode
Swapping to Development environment will display more detailed information about the error that occurred.

Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application.

Why does it tell me I'm not in developer mode?

Here ismy launchSettings.json

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "https://localhost:5000/",
      "sslPort": 5000
    }
  },
  "profiles": {
    "webApp": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:5000"
    }
  }
}

Here is the error from the console log:

 fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[12]
  Message contains error: 'invalid_request', error_description: 'AADB2C90117: The scope 'api://be2d****72d/user_impersonation' provided in the request is not supported.
   Correlation ID: 02c22ec7-6a38-413e-9cb7-68a2a02405c0
    Timestamp: 2020-06-23 04:21:01Z
    ', error_uri: 'error_uri is null'.

Hmmm... Silly me... I had the client ID of the client instead of the client ID of the service. OK, I fixed that and now I get this error:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5000/MicrosoftIdentity/Account/Error  
info: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[7]
      OpenIdConnect was not authenticated. Failure message: Not authenticated
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Account/Error'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Account/Error", area = "MicrosoftIdentity", action = "", controller = ""}. Executing page /Account/Error
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method Microsoft.Identity.Web.UI.Areas.MicrosoftIdentity.Pages.Account.ErrorModel.OnGet - ModelState is Valid

Shucks...

Thanks

Siegfried

Wed Jun 24 2020 Update Part 1 of 2

Progress...

Please update the documentation (both the online web page and the documentation in the README-incremental-instructions.md concerning the editing of the appsettings.json file for the client because it is incomplete and confusing. Also, update the comments in the appsettings.json file too.

I went to the app registration in my AADB2C tenant and clicked "Expose an API" and clicked the little "copy" icon to copy the user_impersonation scope to my clipboard and paste in the appsettings.json file so it now looks like this (for me):

 "TodoListScope": "https://enterprisedemoorg.onmicrosoft.com/aadb2cWebAPICoreToDoListAppIDURI/user_impersonation",

Now I see from my notes that I had previously tried this and it did not work. Now I can log in to the demo web site however. I wonder what changed? Maybe it was that nuget package dentityServer4.AccessTokenValidation that Marilee suggested?

Shucks, it has been so long I'm trying to remember where that "aadb2cWebAPICoreToDoListAppIDURI" came from. When I go to the overview of the WebApp my AADB2C tenant, I see I set the "Application ID URI" to

https://enterprisedemoorg.onmicrosoft.com/aadb2cWebAPICoreToDoListAppIDURI

OK, on to the next error... Stay tuned...

Wed Jun 24 2020 Update Part 2 of 2

Now that I can login with facebook, I would like to see the ToDo list.

However, when I single step with the debugger is that I am not authorized on %SRCROOT%\4-WebApp-your-API\4-2-B2C\Client\Services\TodoListService.cs(line 116). Specifically,

var content = await _httpClient.GetAsync(url)

is returning HttpStatusCode.Unauthorized.

Using the portal I have checked the the client and the server and as far as I can determine, I have correctly exposed the server API (for user_impersonation) and granted API permissions to aadb2cWebAppCoreToDoList (for user_impersonation).

Is there a way attach screen shots so I can show the green circles with the check marks indicating admin consent for enterprisedemoorg?

Anyway, I fiddled with the API Permissions by clicking the "Grand admin consent to enterprisedemorog" until I could see the green circle with the check mark for user_impersonation for https://enterprisedemoorg.onmicrosoft.com/aadb2cWebAPICoreToDoList hoping this would help. It did not...

Thanks

Siegfried

Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
23,317 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Marilee Turscak-MSFT 37,141 Reputation points Microsoft Employee
    2020-06-23T00:07:02.287+00:00

    Hi @SiegfriedHeintze-9929 ,

    I'm looking into your other questions, but for your first question about scopes, you're correct that they're basically just permissions. You use them to specify the permissions applied to a particular resource. For example, to specify the Scope Value of read for the API that has the App ID URI of https://contoso.onmicrosoft.com/api, the scope would be https://contoso.onmicrosoft.com/api/read.

    You can read about this here: https://learn.microsoft.com/en-us/azure/active-directory-b2c/access-tokens

    1. You do appear to need to add the scope for 4-2-B2C. That's specified in this section of the sample.
    2. Based on the documentation it looks like the scope should just be api://{clientId}/user_impersonation

    If that's not working I think it might be worthwhile to create an issue on the sample itself. I'm testing on my end as well to see if I have the same issue and will post back my results.


  2. Marilee Turscak-MSFT 37,141 Reputation points Microsoft Employee
    2020-06-25T04:26:34.2+00:00

    I agree that it's unclear. Sorry for the late response. The content author is travelling this week and I was waiting for confirmation. He said to use this sample instead which has sample scopes defined in the API: https://github.com/Azure-Samples/active-directory-b2c-xamarin-native/issues/131#issuecomment-648536491

    You can use https://fabrikamb2c.onmicrosoft.com/helloapi/demo.read to read the list

    0 comments No comments

  3. Siegfried Heintze 1,906 Reputation points
    2020-06-29T22:28:38.787+00:00

    Wow! What a struggle. Has that developer returned from traveling yet? I've been waiting (and working) a month to get this demo working.

    So far I can log in with my face book account and now I can see my to do list.

    The code for the "ReadScope" in the TodoListService Controller is wrong -- I changed it to UserImpersonationScope and it worked. Note that there are TodoListService Controllers and other TodListService files in the client. I'm not talking about this files in the client code -- the code in the Service is wrong.

    The directions for the TodoListScope in the client's appsettings.json file are wrong and the comments in the appsettings.json file are missleading. The value for the TodoListScope in the appsettings.json file must match the values in the in the app registration for the TodoListService's Application ID URL and this must match the scopes in the exposed API and, in turn, this must match API permissions in the app registration for the client.

    Or at least that is what I did and it worked.

    There is an account button that invokes the non-existent account controller in client. I'd love to have the code for that. I suspect it unpacks the JWT and displays it like https://jwt.ms? That would be educational.

    So before I mark this as the answer, I'd like to have that developer/author of this tutorial confirm what I said is true and provide the missing code for that account button.

    Also:

    As per my discussion with Krishnendu in how-to-use-aad-with-kubernetes.html, I'm going to propose that I use this working demo instead of 1-5-B2C to demonstrate authentication for a Kubernetes application.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.