OpenID - connect-AzureAD works (it seems) but Get-Azureaduser gives me a TokenExpired error

I have the following configures in appsetting, that works great for singing in, SSO etc.

“OIDC”: {
“Enabled”: “true”,
“CallbackPath”: “/auth/signin-oidc”,
“ClientID”: “somethin here”,
“ClientSecret”: “something here”,
“Resource”: “https://graph.microsoft.com/”,
“Authority”: “https://login.microsoftonline.com/something here”,
“ResponseType”: “id_token token”,
“SaveTokens”: “true”,
“CorrelationCookieSameSite”: “”,
“UseTokenLifetime”: true
},

Now I wanted to use retrieve som data from Azure ad.

This does not return any error:
Connect-AzureAD -AadAccessToken $accesstoken -AccountId $IdToken -TenantId something here'

But uncommenting this one gives me an error telling me the token has expired, even if I try immidietly after signing in, same goes for inprivate browsing.
#$AADUser = Get-AzureADUser -ObjectId user@domain.net

Any ideas?

Product: PowerShell Universal
Version: 2.3.0

That’s a new one.

I found an issue on the Az PS repo where others have a similar issue. Unfortunately, it looks like they closed it without actually answering the question.

Is AccountId required?

Oh I just love when that happens.
I suppose i gotta learn how to use Graph then. :sweat_smile:

Thanks

1 Like

I got a quick answer on github on how it was resolved.
I played around with the variables a bit, but havent been able to make it work.

@PorreKaj

Using Parse-JWToken from https://www.michev.info/Blog/Post/2140/decode-jwt-access-and-id-tokens-via-powershell

$upn = (Parse-JWTtoken ($AADtoken)).Unique_name
Connect-AzureAD -AadAccessToken $AADtoken -AccountId $upn -MsAccessToken $Graphtoken

My Token actually is expired.

When logging in, my token is already 1 hour expired.
Time: 22. september 2021 12:26
Token Expiration: 22. september 2021 11:26:09
Token lifetime is 65minutes.

Server and client is in same timezone.
Getting the same issue accessing it from the server.

I wonder if its relevant that Azure is UTC, and I’m 2 hours ahead of that, because that fits :sweat_smile:

Alternativly, the expiration time in the JWT is probably UTC as well, and thus really not expired.

We need a biblical flood to rid this world of timezones please.

oauth 2.0 - Azure AD returns Authentication_ExpiredToken on valid access token - Stack Overflow

A token used to call the Microsoft Graph cannot be used to call the Azure AD Graph API.

Updated the resource line to

Resource": “https://graph.windows.net/”,

and it works - also without the JWT parser - it was helpful though,

Nice find and thanks for the play-by-play! It’s good info.

We’ve got around this by building out a custom MSGraph module - here’s our PS command to grab a new app token. We just call it at the beginning of the API or Dashboard code. You’ll need a registered Azure App

function Get-MSGraphAccessToken {
##########################################################################################
#.SYNOPSIS
# Gets a Microsoft Graph API Accecss Token.  Returns the Access Token.
#
#.DESCRIPTION
# Gets a Microsoft Graph API Access Token equivalent  with the Azure AD app 
# 'PowerShell-MSGraph'.  Permissions are granted via Azure AD.  This command uses 
# the 'client_credential' authorization to Microsoft Graph.  See: 
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow.
#
# NOTE: MSGraph's Access Token's only last for ONE hour
#
#.PARAMETER TenantID
# Tenant ID associated with the environment.  This is an O365 Tenant ID.
#
#.PARAMETER ClientID
# The App ID associated with the API call.  Command expects this is the 'Username' of 
# the 'MSGraph' stored credential of the user.
#
#.PARAMETER ClientSecret
# App secret used to generate the Access Token.  Command expects this is the 'password' of
# the 'MSGraph' stored credential of the user.
#
#.EXAMPLE
# $AccessToken = Get-MSGraphAccessToken
#
#.EXAMPLE
# $AccessToken = Get-MSGraphAccessToken -TenantID $TenantID -ClientID $ClientID -ClientSecret $ClientSecret
# 
#.EXAMPLE
# $AccessToken = Get-MSGraphAccessToken -TenantID 1234-9876 -ClientID 12345987765 -ClientSecret qwerpouc;lkjqwerpoiuc`9870jicice
# 
##########################################################################################
  param (
    # Tenant ID
    [Parameter(Mandatory=$false)]
    [String]
    $TenantID,

    # Client ID
    [Parameter(Mandatory=$false)]
    [String]
    $ClientID,

    # ClientSecret
    [Parameter(Mandatory=$false)]
    [String]
    $ClientSecret
  )

# BEGIN

  # Set the defaults if $ClientID and $ClientSecret aren't found...
  if (!$ClientID -and !$ClientSecret) {
    # Grab the 'MSGraph' Credential from the local session
    $MSGraphCredentials = Get-MessagingCredential -Nickname MSGraph -NonDomainCredentials -NoSave
    if (!$MSGraphCredentials) {
      $tmpstr = "[MSGraph] credential isn't stored in the current PowerShell session.  Run 'Save-Credential' to fix."
      Write-Host $tmpstr -ForegroundColor yellow
      break
    }

    if (!$TenantID) {
      $TenantID = Import-Object -Tablename common_objects -Name GraphTenantID
    }
    $ClientID = "ClientIDHere"
    $ClientSecret = "SecretHere"
  }

# PROCESS
  # Build MSGraph Call Body
  $body = @{
    # using client_credentials API authentication method.  Required for automation
    grant_type = "client_credentials"
    client_id = $ClientID
    client_secret = $ClientSecret
    scope = "https://graph.microsoft.com/.default"
  }

  try {
    $Authorization = Invoke-RestMethod https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token `
    -Method Post `
    -ContentType "application/x-www-form-urlencoded" `
    -Body $body `
    -ErrorAction STOP

    $AccessToken = $Authorization.access_token

    $tmpstr = "Successfully Authenticated to Microsoft Graph"
    Write-Host $tmpstr -ForegroundColor Green
  }
  catch {
    $errstr = $_.exception.message
    $tmpstr = "Error getting MSGraph Access Token : $errstr"
    write-warning $tmpstr
    return $false
  }

# END
  return $AccessToken
}
3 Likes

Thanks Shark, we definetly will transition to Graph as well, so that function will come in handy I’m sure.
I just need to take stuff one step at the time, to see it work, so getting my feet wet with graph while testing the Azure integration wasn’t a good fit :sweat_smile: