{"id":20678240,"url":"https://github.com/codecentric/microsoft-entra-id-playground","last_synced_at":"2025-04-13T18:35:03.093Z","repository":{"id":239195233,"uuid":"798838536","full_name":"codecentric/microsoft-entra-id-playground","owner":"codecentric","description":"This repository provides a setup to demonstrate service-to-service communication, authenticated by Microsoft Entra ID and Microsoft Identity Platform","archived":false,"fork":false,"pushed_at":"2024-05-15T08:36:56.000Z","size":280,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T09:13:15.792Z","etag":null,"topics":["asp-net-core","azure","azuread","iam","microsoft-entra-id","microsoft-identity-platform","oauth2","openid-connect","terraform","token-exchange"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codecentric.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-10T15:22:45.000Z","updated_at":"2024-11-29T13:55:24.000Z","dependencies_parsed_at":"2024-05-15T21:49:57.606Z","dependency_job_id":null,"html_url":"https://github.com/codecentric/microsoft-entra-id-playground","commit_stats":null,"previous_names":["codecentric/entra-id-examples","codecentric/microsoft-entra-id-playground"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fmicrosoft-entra-id-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fmicrosoft-entra-id-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fmicrosoft-entra-id-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fmicrosoft-entra-id-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codecentric","download_url":"https://codeload.github.com/codecentric/microsoft-entra-id-playground/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248761230,"owners_count":21157514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asp-net-core","azure","azuread","iam","microsoft-entra-id","microsoft-identity-platform","oauth2","openid-connect","terraform","token-exchange"],"created_at":"2024-11-16T21:19:31.897Z","updated_at":"2025-04-13T18:35:03.069Z","avatar_url":"https://github.com/codecentric.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Microsoft Entra ID service-to-service authentication playground\n\nThis repository provides a playground to experiment with service to service communication between custom services.\n\nThe repository contains two small REST API services, implemented in ASP.NET Core:\n\n1. CodeRepositoryService\n    * Provides APIs to manage pseudo code repositories\n2. CiService\n    * Provides APIs to create pseudo jobs for repositories, served by CodeRepository service\n    * Communicates either with an app-token, acquired by `client_credentials` flow, or with an user-token, acquired by `on-behalf-of` flow\n\nThe repository can be used to demo four authentication flows:\n\n1. [Authorization code flow using PKCE](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow)\n    * Using swagger-ui\n2. [Client credentials flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow)\n    * Using terraform-generated `ci-service.client_credentials.for.code-repository-service.sh` script and swagger-ui\n    * Alternatively implicitly by creating a CiService job, which uses the [.NET `Microsoft.Identity.Web.DownstreamApi` Library](https://learn.microsoft.com/en-us/entra/identity-platform/scenario-web-api-call-api-app-configuration?tabs=aspnetcore)\n3. [On-behalf-of flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow)\n    * Using terraform-generated `ci-service.device-code.and.on-behalf-of.flow.for.code-repository-service.sh` script and swagger-ui\n    * Alternatively implicitly using the [.NET `Microsoft.Identity.Web.DownstreamApi` Library](https://learn.microsoft.com/en-us/entra/identity-platform/scenario-web-api-call-api-app-configuration?tabs=aspnetcore)\n4. [Device code flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code)\n    * Using terraform-generated `ci-service.device-code.and.on-behalf-of.flow.for.code-repository-service.sh` script and swagger-ui\n\n## Getting started\n\n1. Install [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli#install), [Terraform](https://developer.hashicorp.com/terraform/install?product_intent=terraform), [Docker](https://docs.docker.com/engine/install/)\n2. Login to Azure Tenant with Azure CLI: `az login --tenant \"${YOUR_TENANT_ID}\"`\n    * Nothing bad will happen if you are signed in to a different tenant by accident. The follwing scripts will simply fail to execute.\n3. Create a `config.sh` file, similar to the `config.example.sh`.\n4. Execute `terraform_plan.sh` in the project root directory to inspect planned changes in the Azure tenant.\n5. Execute `setup_and_start.sh` in the project root directory.\n    * Provisions example App registrations via terraform in target Entra ID directory\n    * Creates `appsettings.Compose.json` in `apps/CiService` and `apps/CodeRepositoryService` for docker-compose environment\n    * Creates `appsettings.Development.json` in `apps/CiService` and `apps/CodeRepositoryService` for local debugging\n    * Starts a swagger-ui on http://localhost:8080\n    * Builds and starts CiService and CodeRepositoryService in docker-compose environment\n    * Keeps running and prints logs of `swagger-ui`, `ci-service` and `code-repository-service`\n\n## Example scenario\n\n1. Open swagger-ui in browser on http://localhost:8080\n\n### Create Code Repository\n\n1. Select `CodeRepository` definition (should be the default)\n2. Authorize for `code-repository-service` application\n    1. Click `Authorize` button to open `Available authorizations` dialog\n    2. Scroll to `UserAuthentication` form\n    3. Select `{app-id}/.default` scope.\n    4. Copy `{app-id}` into the `client_id` field\n    5. Click `Authorize` on `Available authorizations` dialog\n    6. Accept consent form for `code-repository-service` application\n        * ![code-repository-service consent form](./docs/images/code_repository_service_consent_dialog.png)\n    7. Click `Close` on `Available authorizations` dialog\n3. Create `test` repository\n    1. Click `Try it out` on `POST /repositories`\n    2. Enter `test` as `repositoryName`\n    3. Click `Execute` button\n4. Inspect logs of `code-repository-service-1` to see the Bearer token\n    * Decode Bearer token. E.g. via https://jwt.io/\n    * ```\n      {\n        \"aud\": \"{CODE_REPOSITORY_CLIENT_ID}\", // Audience: Client ID of the code repository server application. Other applications must not accept this token.\n        \"iss\": \"https://login.microsoftonline.com/{TENANT_ID}/v2.0\", // Issuer: Authorization server which issued this token. Is trusted by the code repository server.\n        \"azp\": \"{CODE_REPOSITORY_CLIENT_ID}\", // Authorized Party: Client ID of the code repository server application.\n        \"name\": \"{user_display_name}\",\n        \"oid\": \"{user_principal_object_id_in_entra_id}\",\n        \"preferred_username\": \"{preferred_username}\",\n        \"scp\": \"UserImpersonation.ReadWrite.All\", // Scopes: Token authorizes to perform read and write operations on behalf of the user. This scope is only valid for the specfic audience (in this case the code repository service)!\n        \"sub\": \"{application_scoped_user_id_string}\",\n        \"tid\": \"{TENANT_ID}\",\n        [...]\n      }\n      ```\n5. Create code resource via `PUT /repositories/{repositoryName}/code` endpoint for the `test` repository and with any content\n\n### Create Job for test repository, authenticating to CodeRepositoryService via app token\n\n1. Select `CiService` definition in swagger-ui\n2. Authorize for `ci-service` application\n    1. Click `Authorize` button to open `Available authorizations` dialog\n    2. Scroll to `UserAuthentication` form\n    3. Select `{app-id}/.default` scope.\n    4. Copy `{app-id}` into the `client_id` field\n    5. Click `Authorize` on `Available authorizations` dialog\n    6. Accept consent form for `ci-service` application\n        * ![ci-service consent form step 1](./docs/images/ci_service_consent_dialog_1.png)\n        * ![ci-service consent form step 2](./docs/images/ci_service_consent_dialog_2.png)\n    7. Click `Close` on `Available authorizations` dialog\n3. Create job for `test` repository with any command and with `impersonateUser=false`\n4. Inspect logs of `ci-service-1` to see the Bearer token\n    * Decode Bearer token. E.g. via https://jwt.io/\n    * ```\n      {\n        \"aud\": \"{CI_SERVICE_CLIENT_ID}\", // Audience: Client ID of the ci service application. Other applications must not accept this token.\n        \"iss\": \"https://login.microsoftonline.com/{TENANT_ID}/v2.0\", // Issuer: Authorization server which issued this token. Is trusted by the ci service.\n        \"azp\": \"{CI_SERVICE_CLIENT_ID}\", // Authorized Party: Client ID of the ci service application.\n        \"name\": \"{user_display_name}\",\n        \"oid\": \"{user_principal_object_id_in_entra_id}\",\n        \"preferred_username\": \"{preferred_username}\",\n        \"scp\": \"UserImpersonation.ReadWrite.All\", // Scopes: Token authorizes to perform read and write operations on behalf of the user. This scope is only valid for the specfic audience (in this case the ci service)!\n        \"sub\": \"{application_scoped_user_id_string}\",\n        \"tid\": \"{TENANT_ID}\",\n      }\n      ```\n5. Inspect logs of `code-repository-service-1` to see the Bearer token\n    * Decode Bearer token. E.g. via https://jwt.io/\n    * ```\n      {\n        \"aud\": \"{CODE_REPOSITORY_CLIENT_ID}\",  // Audience: Client ID of the code repository server application. Other applications must not accept this token.\n        \"iss\": \"https://login.microsoftonline.com/{TENANT_ID}/v2.0\",\n        \"azp\": \"{CI_SERVICE_CLIENT_ID}\", // Authorized Party: Client ID of the ci service application.\n        \"oid\": \"{ci_service_principal_object_id_in_entra_id}\",\n        \"roles\": [\n          \"Repositories.Code.Read.All\" // ci-service has the code-repsitory-service app role \"Repositories.Code.Read.All\" assigned. Therefore it is allowed to read the repository code of any user.\n        ],\n        \"sub\": \"{ci_service_principal_object_id_in_entra_id}\",\n        \"tid\": \"{TENANT_ID}\",\n        [...]\n      }\n      ```\n\n### Create Job for test repository, authenticating to CodeRepositoryService on-behalf of the user via a user token\n\n1. Create job for `test` repository with any command and with `impersonateUser=true`\n2. Inspect logs of `ci-service-1` to see the Bearer token\n   * Should be still the same user token like before \n3. Inspect logs of `code-repository-service-1` to see the Bearer token\n    * Decode Bearer token. E.g. via https://jwt.io/\n    * ```\n      {\n        \"aud\": \"{CODE_REPOSITORY_CLIENT_ID}\",  // Audience: Client ID of the code repository server application. Other applications must not accept this token.\n        \"iss\": \"https://login.microsoftonline.com/{TENANT_ID}/v2.0\",\n        \"azp\": \"{CI_SERVICE_CLIENT_ID}\",  // Authorized Party: Client ID of the ci service application.\n        \"name\": \"{user_display_name}\",\n        \"oid\": \"{user_principal_object_id_in_entra_id}\",\n        \"preferred_username\": \"{preferred_username}\",\n        \"scp\": \"UserImpersonation.Repositories.Code.Read.All\", // Scopes: Token authorizes to read repository code on behalf of the user. This scope is only valid for the specfic audience (in this case the code repository service)!\n        \"sub\": \"{application_scoped_user_id_string}\",\n        \"tid\": \"{TENANT_ID}\",\n        [...]\n      }\n      ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fmicrosoft-entra-id-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodecentric%2Fmicrosoft-entra-id-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fmicrosoft-entra-id-playground/lists"}