AzureAD / microsoft-authentication-library-for-dotnet

Microsoft Authentication Library (MSAL) for .NET
https://aka.ms/msal-net
MIT License
1.41k stars 345 forks source link

[Engineering task] Build automation around session revoke #4636

Open gladjohn opened 9 months ago

gladjohn commented 9 months ago

Task type

Test

Description

Build an API to revoke user/app sessions

Solution

First get a locked user :

https://msidlab.com/api/CreateTempUser?usertype=Basic

To revoke sessions :

https://idlabslabapi.azurewebsites.net/api/Revoke-AzureADUserAllRefreshToken?code=1wFZLTiqfinYjeIGmtWx9-f9Is-5zKCo0D_YG2LwYifcAzFuLrildg==&Username=Locked_c9e19cb229@msidlab4.onmicrosoft.com

The code for the revoke is hosted in this function app for testing. You can find the full code below

https://ms.portal.azure.com/#@microsoft.onmicrosoft.com/resource/subscriptions/6f52c299-a200-4fe1-8822-a3b61cf1f931/resourceGroups/MSIDAnalytics/providers/Microsoft.Web/sites/idlabslabapi/appServices

how to call into this API?

You can use the same information that we use to authenticate to lab API for this new API as well.

How to set this up?

Once you have copy pasted the below code to a function app, specifically one that triggers a PowerShell code. Then you need to do the following changes.

Go to KUDU : https://idlabslabapi.scm.azurewebsites.net/DebugConsole/?shell=powershell

Here you will see these files,

image

Edit the requirements.psd1 and add the following, this enables us to use the AZ modules so we can run Azure Administration PowerShell commands

image

Then edit the profile.ps1 file and add the following. AZ comes with a million modules, so instead of loading them all we are simply loading the ones the script needs.

image

Finally, the app ($ApplicationId = 'e8f7e05f-3ae8-4307-bc34-b26aec3bb4bf'), is registered in msidlab4.com and we use that as a SP to execute these commands in msidlab4.com

Full code (not final) :

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
    $name = $Request.Body.Name
}

# Get the username from the query string
$username = $Request.Query.Username
if (-not $username) {
    $username = $Request.Body.Username
}

$secretValue = [System.Environment]::GetEnvironmentVariable("AppSecret", [System.EnvironmentVariableTarget]::Process)
$SecurePassword = ConvertTo-SecureString -String $secretValue -AsPlainText -Force

$TenantId = 'f645ad92-e38d-4d1a-b510-d1b09a74a8ca';
$ApplicationId = 'e8f7e05f-3ae8-4307-bc34-b26aec3bb4bf';
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecurePassword
$connection = Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential -ErrorAction Stop

# Fetch a specific Azure AD User by UserPrincipalName and select their ObjectId
if ($username) {
    $user = Get-AzADUser -UserPrincipalName $username
    if (-not $user) {
        $result = "User not found."
    } else {
        $userObjectId = $user.Id | Out-String
    }
} else {
    $result = "No username provided."
}

# Conditional logic for username starting with "Locked_"
if ($username -and $username.StartsWith("Locked_")) {
    Revoke-AzureADUserAllRefreshToken -ObjectId $userObjectId
    $result = "Refresh tokens revoked for user."
}
else {
    $result = "Reset can be performed only for locked users."
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $result 
})
bgavrilMS commented 9 months ago

Thanks @gladjohn . I am thinking that these scenarios / int tests are better placed in MIcrosoft.Identity.Web, as it does handle the challenges on its own. Thoughts?