Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion EntraAuth/EntraAuth.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
RootModule = 'EntraAuth.psm1'

# Version number of this module.
ModuleVersion = '1.8.46'
ModuleVersion = '1.8.49'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down
6 changes: 6 additions & 0 deletions EntraAuth/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.8.49 (2025-07-21)

+ New: Federation Provider EntraMSI - added a default federation provider for Managed Identities in Entra.
+ Upd: Invoke-EntraRequest - added parameter `-ContentType`
+ Upd: Connect-EntraService - now supports custom RedirectUris for AuthorizationCode flow

## 1.8.46 (2025-07-11)

+ New: Register-EntraFederationProvider - Register logic to automatically retrieve the assertion needed in a Federated Credential authentication flow.
Expand Down
11 changes: 10 additions & 1 deletion EntraAuth/functions/Authentication/Connect-EntraService.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
Use an interactive logon in your default browser.
This is the default logon experience.

.PARAMETER RedirectUri
The Redirect URI to send with the request.
May be different from the actual local port you want to listen on (e.g. when redirecting to an alternative name on top of localhost).

.PARAMETER BrowserMode
How the browser used for authentication is selected.
Options:
Expand Down Expand Up @@ -248,6 +252,10 @@
[switch]
$Browser,

[Parameter(ParameterSetName = 'Browser')]
[string]
$RedirectUri,

[Parameter(ParameterSetName = 'Browser')]
[ValidateSet('Auto', 'PrintLink')]
[string]
Expand Down Expand Up @@ -473,13 +481,14 @@
if (-not $Scopes) { $scopesToUse = $serviceObject.DefaultScopes }

Write-Verbose "[$serviceName] Connecting via Browser ($($scopesToUse -join ', '))"
try { $result = Connect-ServiceBrowser @commonParam -SelectAccount -Scopes $scopesToUse -NoReconnect:$($serviceObject.NoRefresh) -BrowserMode $BrowserMode -ErrorAction Stop }
try { $result = Connect-ServiceBrowser @commonParam -SelectAccount -Scopes $scopesToUse -NoReconnect:$($serviceObject.NoRefresh) -BrowserMode $BrowserMode -RedirectUri $RedirectUri -ErrorAction Stop }
catch {
Write-Warning "[$serviceName] Failed to connect: $_"
$PSCmdlet.ThrowTerminatingError($_)
}

$token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $effectiveServiceUrl, $false, $authUrl)
$token.RedirectUri = $RedirectUri
$token.SetTokenMetadata($result)
Write-Verbose "[$serviceName] Connected via Browser ($($token.Scopes -join ', '))"
}
Expand Down
8 changes: 8 additions & 0 deletions EntraAuth/functions/Core/Invoke-EntraRequest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

.PARAMETER Header
Any additional headers to include on top of authentication and content-type.

.PARAMETER ContentType
Specify the content-type of this request.
Equivalent to specifying it as a header entry, but added as dedicated parameter for user convenience.

.PARAMETER Service
Which service to execute against.
Expand Down Expand Up @@ -74,6 +78,9 @@

[hashtable]
$Header = @{},

[string]
$ContentType,

[ArgumentCompleter({ Get-ServiceCompletion $args })]
[ValidateScript({ Assert-ServiceName -Name $_ -IncludeTokens })]
Expand Down Expand Up @@ -129,6 +136,7 @@
}

$serviceObject = $script:_EntraEndpoints.$($tokenObject.Service)
if ($ContentType) { $Header['Content-Type'] = $ContentType }
}
process {
$parameters = @{
Expand Down
5 changes: 4 additions & 1 deletion EntraAuth/internal/classes/99-EntraToken.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

[string]$IdentityID
[string]$IdentityType

# Workflow: Browser
[string]$RedirectUri

# Workflow: Client Secret
[System.Security.SecureString]$ClientSecret
Expand Down Expand Up @@ -212,7 +215,7 @@
return
}

$result = Connect-ServiceBrowser @defaultParam -SelectAccount
$result = Connect-ServiceBrowser @defaultParam -SelectAccount -RedirectUri $this.RedirectUri
$this.SetTokenMetadata($result)
}
Refresh {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
.PARAMETER Resource
The resource owning the api permissions / scopes requested.

.PARAMETER RedirectUri
The Redirect URI to send with the request.
May be different from the actual local port you want to listen on (e.g. when redirecting to an alternative name on top of localhost).

.PARAMETER Browser
The path to the browser to use for the authentication flow.
Provide the full path to the executable.
Expand Down Expand Up @@ -83,6 +87,10 @@
[int]
$LocalPort = 8080,

[AllowEmptyString()]
[string]
$RedirectUri,

[string]
$Browser,

Expand All @@ -102,7 +110,8 @@
Add-Type -AssemblyName System.Web
if (-not $Scopes) { $Scopes = @('.default') }

$redirectUri = "http://localhost:$LocalPort"
$localUri = "http://localhost:$LocalPort"
if (-not $RedirectUri) { $RedirectUri = $localUri }
$actualScopes = $Scopes | Resolve-ScopeName -Resource $Resource

if (-not $NoReconnect) {
Expand All @@ -114,7 +123,7 @@
$parameters = @{
client_id = $ClientID
response_type = 'code'
redirect_uri = $redirectUri
redirect_uri = $RedirectUri
response_mode = 'query'
scope = $actualScopes -join ' '
state = $state
Expand All @@ -138,7 +147,8 @@

# Start local server to catch the redirect
$http = [System.Net.HttpListener]::new()
$http.Prefixes.Add("$redirectUri/")
$http.Prefixes.Add(("$RedirectUri/" -replace '//$', '/'))
if ($localUri -ne $RedirectUri) { $http.Prefixes.Add(("$localUri/" -replace '//$', '/')) }
try { $http.Start() }
catch { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Failed to create local http listener on port $LocalPort. Use -LocalPort to select a different port. $_" -Category OpenError }

Expand Down Expand Up @@ -211,7 +221,7 @@ $uriFinal
client_id = $ClientID
scope = $actualScopes -join " "
code = $actualAuthorizationCode
redirect_uri = $redirectUri
redirect_uri = $RedirectUri
grant_type = 'authorization_code'
}
$uri = "$AuthenticationUrl/$TenantID/oauth2/v2.0/token"
Expand Down
18 changes: 17 additions & 1 deletion EntraAuth/internal/scripts/03-FederationProviders.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,20 @@ https://docs.github.com/en/actions/how-tos/writing-workflows/choosing-what-your-
$response.Value
}
}
Register-EntraFederationProvider @param
Register-EntraFederationProvider @param

$param = @{
Name = 'EntraMSI'
Description = 'Authenticate as the Managed Identity in the current context.'
Priority = 20
Test = {
try {
$null = Connect-EntraService -Identity -Resource 'api://AzureADTokenExchange' -ErrorAction Stop
$true
}
catch { $false }
}
code = {
(Connect-EntraService -Identity -Resource 'api://AzureADTokenExchange').AccessToken
}
}