Get OIDC token from the dashboard

I’ve successfully configured the OIDC Azure AD authentication as described in the documentation.
But enabling OIDC seems to be global meaning it will change the authentication to all dashboards.

I was wondering if there is an option to keep the forms or AD authentication and only fetch an Azure AD OIDC token when needed.

For example, I’ve only 1 dashboard that needs to fetch data from Azure and I would like to add a button to this dashboard called “Login to Microsoft”. If click it will open a Office 365 authentication page and once successfully authenticated it will store the token in a variable (similar to $AccessToken).

Is this feasible?

Product: PowerShell Universal
Version: 2.1.4

This type of functionality isn’t built into PSU as it stands. It does seem like you could initiate the flow yourself. Then you could have a callback API Endpoint that Azure AD responds to with the code. You could then use the global cache to store that access token for use within the dashboard.

I’ll try and put together an example when I have some time.

Did you manage to get anywhere with this out of interest, Adam?

I might be barking up the wrong tree here (torn between bumping this thread or this one: oAuth v2.0 - Connecting to the PartnerCenter !) so please shoot me if I’m looking in totally the wrong direction.

I’ve got users authenticating via AzureAD and so have a token in $AccessToken they can query Graph with, get their profile back or query AzureAD - all works wonderfully.

"OIDC": {
        "Enabled": "true",
        "CallbackPath": "/auth/signin-oidc",
        "ClientID": [myappid],
        "ClientSecret": [mysecret],
        "Resource": "https://graph.microsoft.com",
        "Authority": "https://login.microsoftonline.com/[mytenant]",
        "ResponseType": "id_token token",
        "SaveTokens": "true",
        "Scope": "openid profile groups offline_access",
        "UseTokenLifetime": "true",
        "GetUserInfo": "false"
      },

Now I need to work out how to get them a token for the Azure DevOps API (same authority, different scope) - I can do this from my console by running something like Get-MsalToken:

$connectionDetails = @{
'TenantId' = [mytenant]
'ClientId' = [myappid]
'Interactive' = $true
'Scopes' = @('499b84ac-1321-427f-aa17-267ca6975798/user_impersonation') # Azure DevOps Scope
}
$token = Get-MsalToken @connectionDetails

But that puts the user through Interactive Login so when I run it in PSU (running under App Service) it just quietly dies in the background, never producing the prompt.

Feels like there should be some way I can pass $IdToken somewhere to get a new access token without the user re-authenticating?

Any bright ideas gratefully accepted - been banging my head against this wall for a little while now… pretty sure it’d just my novice-level OAuth letting me down! :grinning_face_with_smiling_eyes:

I did not. I was looking at the Get-MsalToken and the only thing I could imagine is that you could somehow request a token with the token you have and then a certficate based on the parameter sets that it has but I am not expert in that cmdlet.

I also wonder if it’s possible to request multiple scopes during AAD auth so you could use the same token against both AzDevOps and Graph.

I’ve tried that from the console and it seems I can only request one scope at a time - if I request both it fails to work for either.

I think Get-MsalToken might be a bit of a dead end tbh, but it at least proves my permissions are good - seems more useful in an interactive session - I’m trying to work out the REST route for it.

I can get an AzDO token from Postman like this using Implicit Flow:

But that seems to rely on having a reply/callback url configured (i.e. the Postman one) - what I’m wondering (and why I ended up in this thread) is if it would be feasible to make an endpoint, say /myauth/callback that received the token and then set it in cache for the user to pick up.

I just can’t work out the order of actions in my head from a user opening the page… something like…?

  • User opens page including a UDDynamic (or something, I like UDDynamics :slight_smile: ) that requests a new AccessToken (using $IdToken) with a replyurl of the endpoint.
  • Endpoint receives token and sets in cache
  • User picks up token from cache

I might be grossly overcomplicating it - if the OIDC login returns a Refresh Token it all gets a lot easier by the sounds of it - PSU shows me $AccessToken and $IdToken - which always appear to be the same, strangely - I don’t suppose it’s just not surfacing a value for refresh_token?

image

I think if I can lay my hands on a refresh token then it can be used for getting new tokens when the first one expires or extra tokens with different scopes:

I’m going to keep bashing away at this - grateful for any suggestions, but I’ll try and keep this thread up to date if I have any success. I’m a bit of a noob with OAuth as you might be able to tell… it’s been on the “we really should be doing that, shouldn’t we?” pile for a while now!

Just closing the loop on this in case anyone runs into the same requirement. The best method we’ve found so far is to use is Get-MsalToken using $AccessToken as a UserAssertation and an App Registration/Client Secret to get a token for ADO (or another Graph scope) :

$ClientID = [app reg with rights to user_impersonation scope in Azure DevOps]
$TenantId = [tenantid]
$ClientSecret = [clientsecret] # retrieve from Vault for security

#Use Get-MsalToken to get an ADO Token

$adotoken = Get-MsalToken -ClientSecret $ClientSecret -ClientId $ClientID -Scopes '499b84ac-1321-427f-aa17-267ca6975798/user_impersonation' -UserAssertion $AccessToken -Authority "https://login.microsoftonline.com/$($TenantId)"

#Create Auth Header using CreateAuthorizationHeader method

$authHeader = @{
    'Authorization' = $adotoken.CreateAuthorizationHeader()
}

#Use token to query ADO

$adourl = 'https://dev.azure.com/myorg/myproject/_apis/pipelines/XXXX/runs/?api-version=6.0-preview.1' # Test query to get list of runs from a Pipeline
$ADOResult = (Invoke-RestMethod -Uri $adourl -Headers $authHeader).Value

New-UDTable -title "Pipeline Runs" -data $ADOResult

3 Likes