diff --git a/1-Authentication/1-sign-in/App/authConfig.js b/1-Authentication/1-sign-in/App/authConfig.js
index 59b8d54..7b37a44 100644
--- a/1-Authentication/1-sign-in/App/authConfig.js
+++ b/1-Authentication/1-sign-in/App/authConfig.js
@@ -5,40 +5,39 @@
*/
const msalConfig = {
- auth: {
- clientId: "Enter_the_Application_Id_Here", // This is the ONLY mandatory field that you need to supply.
- authority: "https://login.microsoftonline.com/Enter_the_Tenant_Info_Here", // Defaults to "https://login.microsoftonline.com/common"
- redirectUri: "Enter_the_Redirect_Uri_Here", // You must register this URI on Azure Portal/App Registration. Defaults to window.location.href
- postLogoutRedirectUri: "Enter_the_Redirect_Uri_Here/signout", // Simply remove this line if you would like navigate to index page after logout.
- navigateToLoginRequestUrl: false, // If "true", will navigate back to the original request location before processing the auth code response.
- },
- cache: {
- cacheLocation: "localStorage", // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO.
- storeAuthStateInCookie: false, // If you wish to store cache items in cookies as well as browser cache, set this to "true".
- },
- system: {
- loggerOptions: {
- loggerCallback: (level, message, containsPii) => {
- if (containsPii) {
- return;
- }
- switch (level) {
- case msal.LogLevel.Error:
- console.error(message);
- return;
- case msal.LogLevel.Info:
- console.info(message);
- return;
- case msal.LogLevel.Verbose:
- console.debug(message);
- return;
- case msal.LogLevel.Warning:
- console.warn(message);
- return;
- }
- }
- }
- }
+ auth: {
+ clientId: 'Enter_the_Application_Id_Here', // This is the ONLY mandatory field that you need to supply.
+ authority: 'https://login.microsoftonline.com/Enter_the_Tenant_Info_Here', // Defaults to "https://login.microsoftonline.com/common"
+ redirectUri: '/', // You must register this URI on Azure Portal/App Registration. Defaults to window.location.href e.g. http://localhost:3000/
+ navigateToLoginRequestUrl: true, // If "true", will navigate back to the original request location before processing the auth code response.
+ },
+ cache: {
+ cacheLocation: 'sessionStorage', // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO.
+ storeAuthStateInCookie: false, // set this to true if you have to support IE
+ },
+ system: {
+ loggerOptions: {
+ loggerCallback: (level, message, containsPii) => {
+ if (containsPii) {
+ return;
+ }
+ switch (level) {
+ case msal.LogLevel.Error:
+ console.error(message);
+ return;
+ case msal.LogLevel.Info:
+ console.info(message);
+ return;
+ case msal.LogLevel.Verbose:
+ console.debug(message);
+ return;
+ case msal.LogLevel.Warning:
+ console.warn(message);
+ return;
+ }
+ },
+ },
+ },
};
/**
@@ -64,6 +63,7 @@ const loginRequest = {
// exporting config object for jest
if (typeof exports !== 'undefined') {
module.exports = {
- msalConfig: msalConfig,
+ msalConfig: msalConfig,
+ loginRequest: loginRequest,
};
}
\ No newline at end of file
diff --git a/1-Authentication/1-sign-in/App/authPopup.js b/1-Authentication/1-sign-in/App/authPopup.js
index cf9f970..0e1c242 100644
--- a/1-Authentication/1-sign-in/App/authPopup.js
+++ b/1-Authentication/1-sign-in/App/authPopup.js
@@ -84,10 +84,12 @@ function signOut() {
// Choose which account to logout from by passing a username.
const logoutRequest = {
- account: myMSALObj.getAccountByUsername(username)
+ account: myMSALObj.getAccountByUsername(username),
+ mainWindowRedirectUri: 'http://localhost:3000/signout',
+ redirectUri: 'http://localhost:3000/redirect.html',
};
- myMSALObj.logout(logoutRequest);
+ myMSALObj.logoutPopup(logoutRequest);
}
selectAccount();
diff --git a/1-Authentication/1-sign-in/App/authRedirect.js b/1-Authentication/1-sign-in/App/authRedirect.js
index 7ac7b4d..e1ec389 100644
--- a/1-Authentication/1-sign-in/App/authRedirect.js
+++ b/1-Authentication/1-sign-in/App/authRedirect.js
@@ -91,8 +91,10 @@ function signOut() {
// Choose which account to logout from by passing a username.
const logoutRequest = {
- account: myMSALObj.getAccountByUsername(username)
+ account: myMSALObj.getAccountByUsername(username),
+ postLogoutRedirectUri: 'http://localhost:3000/signout', // Simply remove this line if you would like navigate to index page after logout.
+
};
- myMSALObj.logout(logoutRequest);
+ myMSALObj.logoutRedirect(logoutRequest);
}
diff --git a/1-Authentication/1-sign-in/App/index.html b/1-Authentication/1-sign-in/App/index.html
index 638b7b4..c8ceb23 100644
--- a/1-Authentication/1-sign-in/App/index.html
+++ b/1-Authentication/1-sign-in/App/index.html
@@ -6,26 +6,22 @@
Microsoft identity platform
+
+
-
-
-
-
-
-
+
+
-
+
Microsoft identity platform
-
+
Sign-in
Sign-out
@@ -53,15 +49,13 @@
-
-
-
+
+
+
+
+
diff --git a/1-Authentication/1-sign-in/App/redirect.html b/1-Authentication/1-sign-in/App/redirect.html
new file mode 100644
index 0000000..175c74c
--- /dev/null
+++ b/1-Authentication/1-sign-in/App/redirect.html
@@ -0,0 +1,7 @@
+
+MSAL Redirect
\ No newline at end of file
diff --git a/1-Authentication/1-sign-in/App/styles.css b/1-Authentication/1-sign-in/App/styles.css
new file mode 100644
index 0000000..3ff3c96
--- /dev/null
+++ b/1-Authentication/1-sign-in/App/styles.css
@@ -0,0 +1,3 @@
+.navbarStyle {
+ padding: .5rem 1rem !important;
+}
\ No newline at end of file
diff --git a/1-Authentication/1-sign-in/AppCreationScripts/AppCreationScripts.md b/1-Authentication/1-sign-in/AppCreationScripts/AppCreationScripts.md
index da7ede5..6e062df 100644
--- a/1-Authentication/1-sign-in/AppCreationScripts/AppCreationScripts.md
+++ b/1-Authentication/1-sign-in/AppCreationScripts/AppCreationScripts.md
@@ -1,45 +1,35 @@
-# Registering the sample apps with the Microsoft identity platform and updating the configuration files using PowerShell
+# Registering sample apps with the Microsoft identity platform and updating configuration files using PowerShell
## Overview
### Quick summary
-1. On Windows run PowerShell as **Administrator** and navigate to the root of the cloned directory
+1. On Windows, run PowerShell as **Administrator** and navigate to the root of the cloned directory
1. In PowerShell run:
```PowerShell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force
```
-1. Run the script to create your Azure AD application and configure the code of the sample application accordingly. (Other ways of running the scripts are described below)
+1. Run the script to create your Azure AD application and configure the code of the sample application accordingly.
```PowerShell
cd .\AppCreationScripts\
- .\Configure.ps1
+ .\Configure.ps1 -TenantId "your test tenant's id" -AzureEnvironmentName "[Optional] - Azure environment, defaults to 'Global'"
```
-1. Open the Visual Studio solution and click start
-
### More details
-The following paragraphs:
-
-- [Registering the sample apps with the Microsoft identity platform and updating the configuration files using PowerShell](#registering-the-sample-apps-with-the-Microsoft-identity-platform-and-updating-the-configuration-files-using-PowerShell)
- - [Overview](#overview)
- - [Quick summary](#quick-summary)
- - [More details](#more-details)
- - [Goal of the provided scripts](#goal-of-the-provided-scripts)
- - [Presentation of the scripts](#presentation-of-the-scripts)
- - [Usage pattern for tests and DevOps scenarios](#usage-pattern-for-tests-and-DevOps-scenarios)
- - [How to use the app creation scripts?](#how-to-use-the-app-creation-scripts)
- - [Pre-requisites](#pre-requisites)
- - [Run the script and start running](#run-the-script-and-start-running)
- - [Four ways to run the script](#four-ways-to-run-the-script)
- - [Option 1 (interactive)](#option-1-interactive)
- - [Option 2 (non-interactive)](#option-2-non-interactive)
- - [Option 3 (Interactive, but create apps in a specified tenant)](#option-3-Interactive-but-create-apps-in-a-specified-tenant)
- - [Option 4 (non-interactive, and create apps in a specified tenant)](#option-4-non-interactive-and-create-apps-in-a-specified-tenant)
- - [Running the script on Azure Sovereign clouds](#running-the-script-on-Azure-Sovereign-clouds)
+- [Goal of the provided scripts](#goal-of-the-provided-scripts)
+ - [Presentation of the scripts](#presentation-of-the-scripts)
+ - [Usage pattern for tests and DevOps scenarios](#usage-pattern-for-tests-and-DevOps-scenarios)
+- [How to use the app creation scripts?](#how-to-use-the-app-creation-scripts)
+ - [Pre-requisites](#pre-requisites)
+ - [Run the script and start running](#run-the-script-and-start-running)
+ - [Four ways to run the script](#four-ways-to-run-the-script)
+ - [Option 1 (interactive)](#option-1-interactive)
+ - [Option 2 (Interactive, but create apps in a specified tenant)](#option-3-Interactive-but-create-apps-in-a-specified-tenant)
+ - [Running the script on Azure Sovereign clouds](#running-the-script-on-Azure-Sovereign-clouds)
## Goal of the provided scripts
@@ -50,14 +40,14 @@ This sample comes with two PowerShell scripts, which automate the creation of th
These scripts are:
- `Configure.ps1` which:
- - creates Azure AD applications and their related objects (permissions, dependencies, secrets),
- - changes the configuration files in the C# and JavaScript projects.
+ - creates Azure AD applications and their related objects (permissions, dependencies, secrets, app roles),
+ - changes the configuration files in the sample projects.
- creates a summary file named `createdApps.html` in the folder from which you ran the script, and containing, for each Azure AD application it created:
- the identifier of the application
- the AppId of the application
- the url of its registration in the [Azure portal](https://portal.azure.com).
-- `Cleanup.ps1` which cleans-up the Azure AD objects created by `Configure.ps1`. Note that this script does not revert the changes done in the configuration files, though. You will need to undo the change from source control (from Visual Studio, or from the command line using, for instance, git reset).
+- `Cleanup.ps1` which cleans-up the Azure AD objects created by `Configure.ps1`. Note that this script does not revert the changes done in the configuration files, though. You will need to undo the change from source control (from Visual Studio, or from the command line using, for instance, `git reset`).
### Usage pattern for tests and DevOps scenarios
@@ -75,22 +65,23 @@ The `Configure.ps1` will stop if it tries to create an Azure AD application whic
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
```
-1. ### (Optionally) install AzureAD PowerShell modules
+### (Optionally) install Microsoft.Graph.Applications PowerShell modules
+
+The scripts install the required PowerShell module (Microsoft.Graph.Applications) for the current user if needed. However, if you want to install if for all users on the machine, you can follow the following steps:
-The scripts install the required PowerShell module (AzureAD) for the current user if needed. However, if you want to install if for all users on the machine, you can follow the following steps:
+1. If you have never done it already, in the PowerShell window, install the Microsoft.Graph.Applications PowerShell modules. For this:
-1. If you have never done it already, in the PowerShell window, install the AzureAD PowerShell modules. For this:
- 1. Open PowerShell as admin (On Windows, Search Powershell in the search bar, right click on it and select Run as administrator).
+ 1. Open PowerShell as admin (On Windows, Search Powershell in the search bar, right click on it and select **Run as administrator**).
2. Type:
```PowerShell
- Install-Module AzureAD
+ Install-Module Microsoft.Graph.Applications
```
or if you cannot be administrator on your machine, run:
```PowerShell
- Install-Module AzureAD -Scope CurrentUser
+ Install-Module Microsoft.Graph.Applications -Scope CurrentUser
```
### Run the script and start running
@@ -105,44 +96,29 @@ The scripts install the required PowerShell module (AzureAD) for the current use
1. Open the Visual Studio solution, and in the solution's context menu, choose **Set Startup Projects**.
1. select **Start** for the projects
-You're done. this just works!
+You're done!
-### Four ways to run the script
+### Two ways to run the script
We advise four ways of running the script:
- Interactive: you will be prompted for credentials, and the scripts decide in which tenant to create the objects,
-- non-interactive: you will provide credentials, and the scripts decide in which tenant to create the objects,
-- Interactive in specific tenant: you will provide the tenant in which you want to create the objects and then you will be prompted for credentials, and the scripts will create the objects,
-- non-interactive in specific tenant: you will provide tenant in which you want to create the objects and credentials, and the scripts will create the objects.
+- Interactive in specific tenant: you will provide the tenant in which you want to create the objects and then you will be prompted for credentials, and the scripts will create the objects,
Here are the details on how to do this.
#### Option 1 (interactive)
-- Just run ``. .\Configure.ps1``, and you will be prompted to sign-in (email address, password, and if needed MFA).
+- Just run ``.\Configure.ps1``, and you will be prompted to sign-in (email address, password, and if needed MFA).
- The script will be run as the signed-in user and will use the tenant in which the user is defined.
Note that the script will choose the tenant in which to create the applications, based on the user. Also to run the `Cleanup.ps1` script, you will need to re-sign-in.
-#### Option 2 (non-interactive)
-
-When you know the identity and credentials of the user in the name of whom you want to create the applications, you can use the non-interactive approach. It's more adapted to DevOps. Here is an example of script you'd want to run in a PowerShell Window
-
-```PowerShell
-$secpasswd = ConvertTo-SecureString "[Password here]" -AsPlainText -Force
-$mycreds = New-Object System.Management.Automation.PSCredential ("[login@tenantName here]", $secpasswd)
-. .\Cleanup.ps1 -Credential $mycreds
-. .\Configure.ps1 -Credential $mycreds
-```
-
-Of course, in real life, you might already get the password as a `SecureString`. You might also want to get the password from KeyVault.
-
-#### Option 3 (Interactive, but create apps in a specified tenant)
+#### Option 2 (Interactive, but create apps in a specified tenant)
if you want to create the apps in a particular tenant, you can use the following option:
-- open the [Azure portal](https://portal.azure.com)
+- Open the [Azure portal](https://portal.azure.com)
- Select the Azure Active directory you are interested in (in the combo-box below your name on the top right of the browser window)
- Find the "Active Directory" object in this tenant
- Go to **Properties** and copy the content of the **Directory Id** property
@@ -154,32 +130,19 @@ $tenantId = "yourTenantIdGuid"
. .\Configure.ps1 -TenantId $tenantId
```
-#### Option 4 (non-interactive, and create apps in a specified tenant)
-
-This option combines option 2 and option 3: it creates the application in a specific tenant. See option 3 for the way to get the tenant Id. Then run:
-
-```PowerShell
-$secpasswd = ConvertTo-SecureString "[Password here]" -AsPlainText -Force
-$mycreds = New-Object System.Management.Automation.PSCredential ("[login@tenantName here]", $secpasswd)
-$tenantId = "yourTenantIdGuid"
-. .\Cleanup.ps1 -Credential $mycreds -TenantId $tenantId
-. .\Configure.ps1 -Credential $mycreds -TenantId $tenantId
-```
-
### Running the script on Azure Sovereign clouds
-All the four options listed above, can be used on any Azure Sovereign clouds. By default, the script targets `AzureCloud`, but it can be changed using the parameter `-AzureEnvironmentName`.
+All the four options listed above can be used on any Azure Sovereign clouds. By default, the script targets `AzureCloud`, but it can be changed using the parameter `-AzureEnvironmentName`.
The acceptable values for this parameter are:
- AzureCloud
- AzureChinaCloud
- AzureUSGovernment
-- AzureGermanyCloud
Example:
```PowerShell
- . .\Cleanup.ps1 -AzureEnvironmentName "AzureGermanyCloud"
- . .\Configure.ps1 -AzureEnvironmentName "AzureGermanyCloud"
+ . .\Cleanup.ps1 -AzureEnvironmentName "AzureUSGovernment"
+ . .\Configure.ps1 -AzureEnvironmentName "AzureUSGovernment"
```
diff --git a/1-Authentication/1-sign-in/AppCreationScripts/Cleanup.ps1 b/1-Authentication/1-sign-in/AppCreationScripts/Cleanup.ps1
index 7b8f14c..72aaef8 100644
--- a/1-Authentication/1-sign-in/AppCreationScripts/Cleanup.ps1
+++ b/1-Authentication/1-sign-in/AppCreationScripts/Cleanup.ps1
@@ -1,26 +1,18 @@
+
[CmdletBinding()]
param(
- [PSCredential] $Credential,
[Parameter(Mandatory=$False, HelpMessage='Tenant ID (This is a GUID which represents the "Directory ID" of the AzureAD tenant into which you want to create the apps')]
[string] $tenantId,
- [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script (it defaults to AzureCloud)')]
+ [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script. Default = Global')]
[string] $azureEnvironmentName
)
-#Requires -Modules AzureAD -RunAsAdministrator
-
-
-if ($null -eq (Get-Module -ListAvailable -Name "AzureAD")) {
- Install-Module "AzureAD" -Scope CurrentUser
-}
-Import-Module AzureAD
-$ErrorActionPreference = "Stop"
Function Cleanup
{
if (!$azureEnvironmentName)
{
- $azureEnvironmentName = "AzureCloud"
+ $azureEnvironmentName = "Global"
}
<#
@@ -31,50 +23,129 @@ Function Cleanup
# $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant
# into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD.
- # Login to Azure PowerShell (interactive if credentials are not already provided:
- # you'll need to sign-in with creds enabling your to create apps in the tenant)
- if (!$Credential -and $TenantId)
+ # Connect to the Microsoft Graph API
+ Write-Host "Connecting to Microsoft Graph"
+
+
+ if ($tenantId -eq "")
{
- $creds = Connect-AzureAD -TenantId $tenantId -AzureEnvironmentName $azureEnvironmentName
+ Connect-MgGraph -Scopes "User.Read.All Organization.Read.All Application.ReadWrite.All" -Environment $azureEnvironmentName
}
- else
+ else
{
- if (!$TenantId)
- {
- $creds = Connect-AzureAD -Credential $Credential -AzureEnvironmentName $azureEnvironmentName
- }
- else
- {
- $creds = Connect-AzureAD -TenantId $tenantId -Credential $Credential -AzureEnvironmentName $azureEnvironmentName
- }
+ Connect-MgGraph -TenantId $tenantId -Scopes "User.Read.All Organization.Read.All Application.ReadWrite.All" -Environment $azureEnvironmentName
}
+
+ $context = Get-MgContext
+ $tenantId = $context.TenantId
- if (!$tenantId)
- {
- $tenantId = $creds.Tenant.Id
- }
- $tenant = Get-AzureADTenantDetail
- $tenantName = ($tenant.VerifiedDomains | Where-Object { $_._Default -eq $True }).Name
+ # Get the user running the script
+ $currentUserPrincipalName = $context.Account
+ $user = Get-MgUser -Filter "UserPrincipalName eq '$($context.Account)'"
+
+ # get the tenant we signed in to
+ $Tenant = Get-MgOrganization
+ $tenantName = $Tenant.DisplayName
+ $verifiedDomain = $Tenant.VerifiedDomains | where {$_.Isdefault -eq $true}
+ $verifiedDomainName = $verifiedDomain.Name
+ $tenantId = $Tenant.Id
+
+ Write-Host ("Connected to Tenant {0} ({1}) as account '{2}'. Domain is '{3}'" -f $Tenant.DisplayName, $Tenant.Id, $currentUserPrincipalName, $verifiedDomainName)
+
# Removes the applications
- Write-Host "Cleaning-up applications from tenant '$tenantName'"
+ Write-Host "Cleaning-up applications from tenant '$tenantId'"
- Write-Host "Removing 'spa' (ms-identity-javascript-c1s1) if needed"
- Get-AzureADApplication -Filter "DisplayName eq 'ms-identity-javascript-c1s1'" | ForEach-Object {Remove-AzureADApplication -ObjectId $_.ObjectId }
- $apps = Get-AzureADApplication -Filter "DisplayName eq 'ms-identity-javascript-c1s1'"
+ Write-Host "Removing 'client' (ms-identity-javascript-c1s1) if needed"
+ try
+ {
+ Get-MgApplication -Filter "DisplayName eq 'ms-identity-javascript-c1s1'" | ForEach-Object {Remove-MgApplication -ApplicationId $_.Id }
+ }
+ catch
+ {
+ $message = $_
+ Write-Warning $Error[0]
+ Write-Host "Unable to remove the application 'ms-identity-javascript-c1s1'. Error is $message. Try deleting manually." -ForegroundColor White -BackgroundColor Red
+ }
+
+ Write-Host "Making sure there are no more (ms-identity-javascript-c1s1) applications found, will remove if needed..."
+ $apps = Get-MgApplication -Filter "DisplayName eq 'ms-identity-javascript-c1s1'" | Format-List Id, DisplayName, AppId, SignInAudience, PublisherDomain
+
if ($apps)
{
- Remove-AzureADApplication -ObjectId $apps.ObjectId
+ Remove-MgApplication -ApplicationId $apps.Id
}
foreach ($app in $apps)
{
- Remove-AzureADApplication -ObjectId $app.ObjectId
+ Remove-MgApplication -ApplicationId $app.Id
Write-Host "Removed ms-identity-javascript-c1s1.."
}
+
# also remove service principals of this app
- Get-AzureADServicePrincipal -filter "DisplayName eq 'ms-identity-javascript-c1s1'" | ForEach-Object {Remove-AzureADServicePrincipal -ObjectId $_.Id -Confirm:$false}
-
+ try
+ {
+ Get-MgServicePrincipal -filter "DisplayName eq 'ms-identity-javascript-c1s1'" | ForEach-Object {Remove-MgServicePrincipal -ServicePrincipalId $_.Id -Confirm:$false}
+ }
+ catch
+ {
+ $message = $_
+ Write-Warning $Error[0]
+ Write-Host "Unable to remove ServicePrincipal 'ms-identity-javascript-c1s1'. Error is $message. Try deleting manually from Enterprise applications." -ForegroundColor White -BackgroundColor Red
+ }
+}
+
+# Pre-requisites
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph")) {
+ Install-Module "Microsoft.Graph" -Scope CurrentUser
+}
+
+#Import-Module Microsoft.Graph
+
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Authentication")) {
+ Install-Module "Microsoft.Graph.Authentication" -Scope CurrentUser
+}
+
+Import-Module Microsoft.Graph.Authentication
+
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Identity.DirectoryManagement")) {
+ Install-Module "Microsoft.Graph.Identity.DirectoryManagement" -Scope CurrentUser
+}
+
+Import-Module Microsoft.Graph.Identity.DirectoryManagement
+
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Applications")) {
+ Install-Module "Microsoft.Graph.Applications" -Scope CurrentUser
+}
+
+Import-Module Microsoft.Graph.Applications
+
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Groups")) {
+ Install-Module "Microsoft.Graph.Groups" -Scope CurrentUser
+}
+
+Import-Module Microsoft.Graph.Groups
+
+if ($null -eq (Get-Module -ListAvailable -Name "Microsoft.Graph.Users")) {
+ Install-Module "Microsoft.Graph.Users" -Scope CurrentUser
+}
+
+Import-Module Microsoft.Graph.Users
+
+$ErrorActionPreference = "Stop"
+
+
+try
+{
+ Cleanup -tenantId $tenantId -environment $azureEnvironmentName
+}
+catch
+{
+ $_.Exception.ToString() | out-host
+ $message = $_
+ Write-Warning $Error[0]
+ Write-Host "Unable to register apps. Error is $message." -ForegroundColor White -BackgroundColor Red
}
-Cleanup -Credential $Credential -tenantId $TenantId
\ No newline at end of file
+Write-Host "Disconnecting from tenant"
+Disconnect-MgGraph
diff --git a/1-Authentication/1-sign-in/AppCreationScripts/Configure.ps1 b/1-Authentication/1-sign-in/AppCreationScripts/Configure.ps1
index fa0acd8..a2043d4 100644
--- a/1-Authentication/1-sign-in/AppCreationScripts/Configure.ps1
+++ b/1-Authentication/1-sign-in/AppCreationScripts/Configure.ps1
@@ -1,26 +1,64 @@
+
[CmdletBinding()]
param(
- [PSCredential] $Credential,
[Parameter(Mandatory=$False, HelpMessage='Tenant ID (This is a GUID which represents the "Directory ID" of the AzureAD tenant into which you want to create the apps')]
[string] $tenantId,
- [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script (it defaults to AzureCloud)')]
+ [Parameter(Mandatory=$False, HelpMessage='Azure environment to use while running the script. Default = Global')]
[string] $azureEnvironmentName
)
-#Requires -Modules AzureAD -RunAsAdministrator
-
<#
This script creates the Azure AD applications needed for this sample and updates the configuration files
for the visual Studio projects from the data in the Azure AD applications.
- Before running this script you need to install the AzureAD cmdlets as an administrator.
- For this:
- 1) Run Powershell as an administrator
- 2) in the PowerShell window, type: Install-Module AzureAD
-
- There are four ways to run this script. For more information, read the AppCreationScripts.md file in the same folder as this script.
+ In case you don't have Microsoft.Graph.Applications already installed, the script will automatically install it for the current user
+
+ There are two ways to run this script. For more information, read the AppCreationScripts.md file in the same folder as this script.
#>
+<#.Description
+ This function takes a string input as a single line, matches a key value and replaces with the replacement value
+#>
+Function UpdateLine([string] $line, [string] $value)
+{
+ $index = $line.IndexOf(':')
+ $lineEnd = ''
+
+ if($line[$line.Length - 1] -eq ','){ $lineEnd = ',' }
+
+ if ($index -ige 0)
+ {
+ $line = $line.Substring(0, $index+1) + " " + '"' + $value+ '"' + $lineEnd
+ }
+ return $line
+}
+
+<#.Description
+ This function takes a dictionary of keys to search and their replacements and replaces the placeholders in a text file
+#>
+Function UpdateTextFile([string] $configFilePath, [System.Collections.HashTable] $dictionary)
+{
+ $lines = Get-Content $configFilePath
+ $index = 0
+ while($index -lt $lines.Length)
+ {
+ $line = $lines[$index]
+ foreach($key in $dictionary.Keys)
+ {
+ if ($line.Contains($key))
+ {
+ $lines[$index] = UpdateLine $line $dictionary[$key]
+ }
+ }
+ $index++
+ }
+
+ Set-Content -Path $configFilePath -Value $lines -Force
+}
+
+<#.Description
+ This function takes a string input as a single line, matches a key value and replaces with the replacement value
+#>
Function ReplaceInLine([string] $line, [string] $key, [string] $value)
{
$index = $line.IndexOf($key)
@@ -32,6 +70,9 @@ Function ReplaceInLine([string] $line, [string] $key, [string] $value)
return $line
}
+<#.Description
+ This function takes a dictionary of keys to search and their replacements and replaces the placeholders in a text file
+#>
Function ReplaceInTextFile([string] $configFilePath, [System.Collections.HashTable] $dictionary)
{
$lines = Get-Content $configFilePath
@@ -52,112 +93,196 @@ Function ReplaceInTextFile([string] $configFilePath, [System.Collections.HashTab
Set-Content -Path $configFilePath -Value $lines -Force
}
-Set-Content -Value "" -Path createdApps.html
-Add-Content -Value "Application AppId Url in the Azure portal " -Path createdApps.html
-
-$ErrorActionPreference = "Stop"
-Function ConfigureApplications
+<#.Description
+ This function takes a string as input and creates an instance of an Optional claim object
+#>
+Function CreateOptionalClaim([string] $name)
{
+ <#.Description
+ This function creates a new Azure AD optional claims with default and provided values
+ #>
+
+ $appClaim = New-Object Microsoft.Graph.PowerShell.Models.MicrosoftGraphOptionalClaim
+ $appClaim.AdditionalProperties = New-Object System.Collections.Generic.List[string]
+ $appClaim.Source = $null
+ $appClaim.Essential = $false
+ $appClaim.Name = $name
+ return $appClaim
+}
+
<#.Description
- This function creates the Azure AD applications for the sample in the provided Azure AD tenant and updates the
- configuration files in the client and service project of the visual studio solution (App.Config and Web.Config)
- so that they are consistent with the Applications parameters
+ Primary entry method to create and configure app registrations
#>
- $commonendpoint = "common"
+Function ConfigureApplications
+{
+ $isOpenSSl = 'N' #temporary disable open certificate creation
+
+ <#.Description
+ This function creates the Azure AD applications for the sample in the provided Azure AD tenant and updates the
+ configuration files in the client and service project of the visual studio solution (App.Config and Web.Config)
+ so that they are consistent with the Applications parameters
+ #>
if (!$azureEnvironmentName)
{
- $azureEnvironmentName = "AzureCloud"
+ $azureEnvironmentName = "Global"
}
- # $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant
- # into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD.
-
- # Login to Azure PowerShell (interactive if credentials are not already provided:
- # you'll need to sign-in with creds enabling your to create apps in the tenant)
- if (!$Credential -and $TenantId)
- {
- $creds = Connect-AzureAD -TenantId $tenantId -AzureEnvironmentName $azureEnvironmentName
+ # Connect to the Microsoft Graph API, non-interactive is not supported for the moment (Oct 2021)
+ Write-Host "Connecting to Microsoft Graph"
+ if ($tenantId -eq "") {
+ Connect-MgGraph -Scopes "User.Read.All Organization.Read.All Application.ReadWrite.All" -Environment $azureEnvironmentName
}
- else
- {
- if (!$TenantId)
- {
- $creds = Connect-AzureAD -Credential $Credential -AzureEnvironmentName $azureEnvironmentName
- }
- else
- {
- $creds = Connect-AzureAD -TenantId $tenantId -Credential $Credential -AzureEnvironmentName $azureEnvironmentName
- }
+ else {
+ Connect-MgGraph -TenantId $tenantId -Scopes "User.Read.All Organization.Read.All Application.ReadWrite.All" -Environment $azureEnvironmentName
}
+
+ $context = Get-MgContext
+ $tenantId = $context.TenantId
- if (!$tenantId)
- {
- $tenantId = $creds.Tenant.Id
- }
+ # Get the user running the script
+ $currentUserPrincipalName = $context.Account
+ $user = Get-MgUser -Filter "UserPrincipalName eq '$($context.Account)'"
+ # get the tenant we signed in to
+ $Tenant = Get-MgOrganization
+ $tenantName = $Tenant.DisplayName
+ $verifiedDomain = $Tenant.VerifiedDomains | where {$_.Isdefault -eq $true}
+ $verifiedDomainName = $verifiedDomain.Name
+ $tenantId = $Tenant.Id
- $tenant = Get-AzureADTenantDetail
- $tenantName = ($tenant.VerifiedDomains | Where { $_._Default -eq $True }).Name
-
- # Get the user running the script to add the user as the app owner
- $user = Get-AzureADUser -ObjectId $creds.Account.Id
+ Write-Host ("Connected to Tenant {0} ({1}) as account '{2}'. Domain is '{3}'" -f $Tenant.DisplayName, $Tenant.Id, $currentUserPrincipalName, $verifiedDomainName)
- # Create the spa AAD application
+ # Create the client AAD application
Write-Host "Creating the AAD application (ms-identity-javascript-c1s1)"
# create the application
- $spaAadApplication = New-AzureADApplication -DisplayName "ms-identity-javascript-c1s1" `
- -HomePage "http://localhost:3000" `
- -ReplyUrls "http://localhost:3000" `
- -IdentifierUris "https://$tenantName/ms-identity-javascript-c1s1" `
- -PublicClient $False
-
- # create the service principal of the newly created application
- $currentAppId = $spaAadApplication.AppId
- $spaServicePrincipal = New-AzureADServicePrincipal -AppId $currentAppId -Tags {WindowsAzureActiveDirectoryIntegratedApp}
-
- # add the user running the script as an app owner if needed
- $owner = Get-AzureADApplicationOwner -ObjectId $spaAadApplication.ObjectId
- if ($owner -eq $null)
- {
- Add-AzureADApplicationOwner -ObjectId $spaAadApplication.ObjectId -RefObjectId $user.ObjectId
- Write-Host "'$($user.UserPrincipalName)' added as an application owner to app '$($spaServicePrincipal.DisplayName)'"
- }
-
-
- Write-Host "Done creating the spa application (ms-identity-javascript-c1s1)"
-
- # URL of the AAD application in the Azure portal
- # Future? $spaPortalUrl = "https://portal.azure.com/#@"+$tenantName+"/blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/"+$spaAadApplication.AppId+"/objectId/"+$spaAadApplication.ObjectId+"/isMSAApp/"
- $spaPortalUrl = "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/"+$spaAadApplication.AppId+"/objectId/"+$spaAadApplication.ObjectId+"/isMSAApp/"
- Add-Content -Value "spa $currentAppId ms-identity-javascript-c1s1 " -Path createdApps.html
-
-
- # Update config file for 'spa'
- $configFile = $pwd.Path + "\..\App\authConfig.js"
- Write-Host "Updating the sample code ($configFile)"
- $dictionary = @{ "Enter_the_Application_Id_Here" = $spaAadApplication.AppId; "Enter_the_Tenant_Info_Here" = $tenantId; "Enter_the_Redirect_Uri_Here" = $spaAadApplication.ReplyUrls };
- ReplaceInTextFile -configFilePath $configFile -dictionary $dictionary
- Write-Host ""
- Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
- Write-Host "IMPORTANT: Please follow the instructions below to complete a few manual step(s) in the Azure portal":
- Write-Host "- For 'spa'"
- Write-Host " - Navigate to '$spaPortalUrl'"
- Write-Host " - Navigate to the Manifest page, find the entry for 'replyUrlsWithType' and change the value to 'Spa'" -ForegroundColor Red
-
- Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
-
- Add-Content -Value "
" -Path createdApps.html
+ $clientAadApplication = New-MgApplication -DisplayName "ms-identity-javascript-c1s1" `
+ -Spa `
+ @{ `
+ RedirectUris = "http://localhost:3000", "http://localhost:3000/redirect"; `
+ } `
+ -SignInAudience AzureADMyOrg `
+ #end of command
+
+ $currentAppId = $clientAadApplication.AppId
+ $currentAppObjectId = $clientAadApplication.Id
+
+ $tenantName = (Get-MgApplication -ApplicationId $currentAppObjectId).PublisherDomain
+ #Update-MgApplication -ApplicationId $currentAppObjectId -IdentifierUris @("https://$tenantName/ms-identity-javascript-c1s1")
+
+ # create the service principal of the newly created application
+ $clientServicePrincipal = New-MgServicePrincipal -AppId $currentAppId -Tags {WindowsAzureActiveDirectoryIntegratedApp}
+
+ # add the user running the script as an app owner if needed
+ $owner = Get-MgApplicationOwner -ApplicationId $currentAppObjectId
+ if ($owner -eq $null)
+ {
+ New-MgApplicationOwnerByRef -ApplicationId $currentAppObjectId -BodyParameter = @{"@odata.id" = "htps://graph.microsoft.com/v1.0/directoryObjects/$user.ObjectId"}
+ Write-Host "'$($user.UserPrincipalName)' added as an application owner to app '$($clientServicePrincipal.DisplayName)'"
+ }
+
+ # Add Claims
+
+ $optionalClaims = New-Object Microsoft.Graph.PowerShell.Models.MicrosoftGraphOptionalClaims
+ $optionalClaims.AccessToken = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphOptionalClaim]
+ $optionalClaims.IdToken = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphOptionalClaim]
+ $optionalClaims.Saml2Token = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphOptionalClaim]
+
+ # Add Optional Claims
+
+ $newClaim = CreateOptionalClaim -name "acct"
+ $optionalClaims.IdToken += ($newClaim)
+ Update-MgApplication -ApplicationId $currentAppObjectId -OptionalClaims $optionalClaims
+ Write-Host "Done creating the client application (ms-identity-javascript-c1s1)"
+
+ # URL of the AAD application in the Azure portal
+ # Future? $clientPortalUrl = "https://portal.azure.com/#@"+$tenantName+"/blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/"+$currentAppId+"/objectId/"+$currentAppObjectId+"/isMSAApp/"
+ $clientPortalUrl = "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/"+$currentAppId+"/objectId/"+$currentAppObjectId+"/isMSAApp/"
+
+ Add-Content -Value "client $currentAppId ms-identity-javascript-c1s1 " -Path createdApps.html
+
+ # print the registered app portal URL for any further navigation
+ Write-Host "Successfully registered and configured that app registration for 'ms-identity-javascript-c1s1' at `n $clientPortalUrl" -ForegroundColor Green
+
+ # Update config file for 'client'
+ # $configFile = $pwd.Path + "\..\App\authConfig.js"
+ $configFile = $(Resolve-Path ($pwd.Path + "\..\App\authConfig.js"))
+
+ $dictionary = @{ "Enter_the_Application_Id_Here" = $clientAadApplication.AppId;"Enter_the_Tenant_Info_Here" = $tenantId };
+
+ Write-Host "Updating the sample config '$configFile' with the following config values:" -ForegroundColor Yellow
+ $dictionary
+ Write-Host "-----------------"
+
+ ReplaceInTextFile -configFilePath $configFile -dictionary $dictionary
+
+if($isOpenSSL -eq 'Y')
+{
+ Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
+ Write-Host "You have generated certificate using OpenSSL so follow below steps: "
+ Write-Host "Install the certificate on your system from current folder."
+ Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
}
+Add-Content -Value "