Showing posts with label OAuth. Show all posts
Showing posts with label OAuth. Show all posts

Sunday, November 30, 2025

How to Generate the Correct OneDrive OAuth Token in ServiceNow

If your ServiceNow instance keeps uploading files into the wrong OneDrive folder, it means the OAuth token was issued for the wrong Microsoft account. This is the exact procedure to generate a correct token for the right service account, using a manually configured OAuth Application Registry — the approach behind a custom-built OneDrive integration rather than ServiceNow's official OneDrive Spoke.

A note on scope before starting: this procedure applies specifically to a custom OAuth setup built around a System OAuth Application Registry entry, which relies on the delegated permissions model — the same mechanics covered in this blog's companion articles on why ServiceNow needs two Microsoft identities, and why uploads land in the wrong folder in the first place. If your integration instead runs through ServiceNow's official Microsoft OneDrive Spoke, authentication is typically managed through its own Connection & Credential Alias — often set up with a certificate-based application identity rather than a delegated user session — and this specific token-regeneration procedure won't apply the same way. Confirm which of the two you're actually running before following the steps below.

Prerequisites

  • OneDrive service account
  • Azure AD (Entra ID) admin account, for App Registration
  • OneDrive OAuth profile configured in ServiceNow
  • Valid Client ID and Client Secret

Why This Procedure Is Necessary

With SSO environments:

  • VDI login automatically logs users into Microsoft.
  • Teams/Outlook auto-start with cached credentials.
  • Office apps silently authenticate.

This means clicking Get OAuth Token will always use whatever Microsoft session is active — even if you logged into ServiceNow with a different account.

Step-by-Step Procedure

Step 1 — Completely Log Out of All Microsoft Sessions

You must remove all cached Microsoft identity data:

  • Sign out of Teams.
  • Sign out of Outlook.
  • Stop the OneDrive sync client.
  • Close Office apps.
  • Log out of Office.com.
  • Clear browser cookies.
  • Restart the browser.
  • Optionally, reboot the VDI session.

Step 2 — Open a New Incognito Window

Do not use a normal window — normal windows share cookies from the VDI session you just tried to clear.

Step 3 — Sign In to Microsoft Manually With the OneDrive Account

In the incognito window:

  • Go to https://login.microsoftonline.com.
  • Sign in as the OneDrive service account.
  • Complete MFA if required.

At this stage, Microsoft knows the identity that should receive the OAuth token.

Step 4 — Log In to ServiceNow With the Same Service Account

Still in the same incognito window:

  • Log in to ServiceNow as the OneDrive service account.
  • Do not use impersonation — impersonation only changes the ServiceNow-side identity, not the Microsoft session behind it.

Step 5 — Navigate to the OneDrive OAuth Profile

Go to:

System OAuth → Application Registry → Your OneDrive OAuth Profile

Step 6 — Click "Get OAuth Token"

This time:

  • Microsoft sees the OneDrive service account as the active session.
  • Microsoft issues the OAuth token for the OneDrive service account.
  • ServiceNow stores the token under the OneDrive service account's user context.

Step 7 — Validate the Token

Run a test action against your configured OneDrive integration — for example, a Create Folder action. The folder should appear under the OneDrive service account's OneDrive path, not any other account's.

What If It Still Shows the Wrong Account?

Then the VDI or OS-level Microsoft session is still active. Use one of these options:

  • Try a different browser.
  • Use an entirely different machine.
  • Use a private Windows account profile.
  • Disable Teams auto-login temporarily.
  • Use a clean VM with no corporate SSO session.

Once the correct token is captured, normal usage will no longer rely on the end user's Microsoft session — the token, once correctly issued, stays valid independent of whoever's logged into Windows or Teams afterward.

If You're Doing This Often, Consider the Structural Fix

This procedure works, but it's worth being honest about what it actually is: a careful manual workaround for a session-dependent authentication model. If this keeps recurring — a token needs regenerating every time someone's VDI session changes, or every time a service account's cached credentials expire — that's a signal worth acting on, not just repeating the fix for. Moving to ServiceNow's official Microsoft OneDrive Spoke, configured with a certificate-based application identity rather than delegated permissions, removes the session dependency at its root. See this blog's companion article on wrong-folder uploads for the specific setup details, including the Sites.Selected scoping option that keeps the application's access appropriately limited rather than organization-wide.

Summary

To ensure ServiceNow writes files into the correct OneDrive folder:

  • The OneDrive service account must be the active Microsoft identity when generating the OAuth token.
  • Logging in to ServiceNow as that same service account ensures correct token storage.
  • Clearing cached Microsoft sessions is essential in SSO environments.

Following these steps guarantees the OAuth token belongs to the correct storage account every time — and if you find yourself following them often, that's the cue to look at the Spoke-based alternative instead of treating this as a permanent routine.

Saturday, November 29, 2025

ServiceNow + OneDrive OAuth Tokens: Why Files Keep Uploading to the Wrong User’s Folder

Many ServiceNow teams experience a confusing issue:

"We clicked Get OAuth Token, but files upload to the wrong user's OneDrive folder."

This happens even when logged in as a different ServiceNow user, or when impersonating. The root cause is not in ServiceNow at all — it's in Microsoft session handling. Let's explain the mechanics first, then cover the two ways to actually get past this permanently rather than managing around it every time.

1. OAuth Token Is Issued to the Active Microsoft Session

When you click Get OAuth Token in ServiceNow:

  • ServiceNow triggers an OAuth flow.
  • Microsoft checks who is currently signed in.
  • Microsoft issues an OAuth token for that account.
  • ServiceNow stores that token under the user record.

ServiceNow is simply the redirect channel here. Microsoft chooses the identity, based entirely on whatever browser session happens to be active at that moment.

2. VDI / SSO / Teams Auto-Login Makes This Worse

Many enterprise users log into a VDI or laptop using SSO, causing Microsoft apps like Teams, Outlook, Office.com, and the OneDrive client to automatically authenticate using a personal or admin account.

This means:

  • Even if you open an Incognito window.
  • Even if you log in to ServiceNow as a different user.
  • Even if you impersonate.

Microsoft will still issue a token belonging to the cached session — none of the ServiceNow-side workarounds above touch Microsoft's own session state.

3. Why You Were Never Prompted for Microsoft Credentials

Because the browser already had a valid Microsoft authentication session via PingOne (if used), native Windows sign-in, Office apps auto-login, or a VDI identity provider. Microsoft never prompts again unless that session is explicitly cleared.

4. How to Generate a Token for the Correct OneDrive Account

You must ensure the Microsoft session belongs to the OneDrive service account.

Correct procedure:

  1. Sign out from all Microsoft apps (Teams, Outlook, OneDrive sync client).
  2. Clear browser cookies.
  3. Open a clean incognito window.
  4. Manually sign in to Microsoft using the OneDrive service account.
  5. Log in to ServiceNow using the same account (real login, not impersonation).
  6. Click Get OAuth Token.

Now the token will belong to the correct OneDrive account.

5. Why Impersonation Does Not Work

Impersonation changes only the ServiceNow identity. It does not — and cannot — change the Microsoft identity, browser sessions, SSO sessions, or Office login state. Impersonation is entirely a ServiceNow-side concept; Microsoft's authentication layer has no awareness of it whatsoever. Thus, impersonation cannot control where files get stored.

6. The Newer Alternative: The Official Microsoft OneDrive / SharePoint Online Spoke

Everything above describes how to correctly manage the delegated OAuth flow — but it's worth being direct about what it actually is: a manual, session-dependent process that has to be redone carefully every time the wrong Microsoft identity gets cached. If this keeps happening on your instance, it's worth considering ServiceNow's official Microsoft OneDrive Spoke and Microsoft SharePoint Online Spoke, available through Integration Hub, as a structural fix rather than a repeated manual procedure.

Here's what makes this genuinely different, not just more convenient: the SharePoint Online Spoke's standard setup uses a certificate-based application identity — an Azure app registration authenticating with a certificate rather than a delegated user session — with the option to scope access down to Sites.Selected instead of the broader Sites.FullControl.All. This is the application-permissions model, the same structural fix discussed in this blog's companion article on why ServiceNow needs two Microsoft identities. Because there's no signed-in user involved, there's no "whichever session happens to be cached" problem to manage at all — the identity is fixed at the application level, not determined by whoever's browser session is active when a token gets requested.

A few practical setup notes if you go this route:

  • The Spoke uses a Connection & Credential Alias to store its authentication configuration — worth knowing that these records are not captured in Update Sets, so each environment (Dev, Test, Prod) needs its connection, credential, alias, and app registration configured fresh rather than promoted through the normal change pipeline. Static values like the OAuth app registry details can be stored in a system property and referenced across environments to reduce repeated manual entry.
  • If you hit authentication errors during setup specifically, check Key Management > Module Access Policies — this module isn't always available to admins by default, and a missing or misconfigured target script entry (commonly surfaced as an OAuthUtilSPJWTOnline-related script) is a known, specific cause of setup-time authentication failures.
  • Choose Sites.Selected over Sites.FullControl.All during setup wherever your integration only needs to reach specific document libraries — this keeps the Spoke's broader application-level reach appropriately scoped rather than granting organization-wide access by default.

Summary

ServiceNow does not decide where OneDrive files go — the Microsoft account active during OAuth does, if you're using the delegated flow described in Sections 1 through 5. To fix file uploads going to the wrong folder under that model:

  • Ensure the correct Microsoft identity is active.
  • Use clean browser isolation.
  • Log in to ServiceNow with the OneDrive service account before generating the token.

Once properly configured, files will upload into the correct OneDrive or SharePoint folder — but if this is a recurring operational headache rather than a one-time setup issue, moving to the certificate-based Microsoft OneDrive or SharePoint Online Spoke removes the session-dependency at its root, rather than requiring the careful manual procedure above every time it resurfaces.

Understanding ServiceNow + OneDrive Integration: Why Two Microsoft Accounts Are Required

Integrating ServiceNow with Microsoft OneDrive often confuses teams — especially when they realize two different roles are involved, sometimes represented by two different Microsoft accounts:

  1. The identity that ends up owning the uploaded files (the OneDrive/runtime identity)
  2. The Entra ID administrative identity used to configure the integration itself

Why does this split exist, and — this is the part most explanations skip — is it actually unavoidable? Let's break it down, including the architecture that avoids the split entirely.

1. The Runtime Identity — Where Files Actually Land

This is the identity that actually owns the files ServiceNow uploads. When ServiceNow pushes a document to OneDrive, it goes to the personal or shared folder belonging to whichever identity's OAuth token ServiceNow is holding at the time.

This identity represents where the documents live — not who configured the integration.

2. The Entra ID Admin Identity — Configuring the Integration

The Entra ID (formerly Azure AD) administrative account is used only for configuring the integration. This account:

  • Creates the App Registration
  • Generates the Client ID
  • Creates and rotates the Client Secret
  • Grants Microsoft Graph API permissions
  • Approves admin consent

This account does not store documents and doesn't represent a file-owning user on the OneDrive side — it only provides the OAuth infrastructure the integration runs on.

Worth being precise about: both of these are Microsoft Entra ID identities under the hood — there isn't a separate "OneDrive account" type distinct from an Entra ID account. The real distinction is about role in the OAuth flow: one identity does one-time administrative setup, and a separate identity's session (in one specific architecture, covered next) determines where files actually land at runtime.

3. Why This Split Exists — In the Delegated Permissions Model Specifically

This is the detail that changes everything about how to think about this problem: the two-identity split described above is a real, well-documented consequence of delegated permissions — one of two permission models Microsoft Graph API supports for OneDrive access — not an unavoidable fact about ServiceNow+OneDrive integration in general.

In the delegated model, the app calls Microsoft Graph on behalf of a signed-in user. Two identities genuinely participate: a real user who consents to delegate their access, and the application (via its Entra ID registration) that receives temporary delegated access to act within that user's permissions. The application's effective permissions are the intersection of what it's been granted and what that specific signed-in user is actually allowed to do — it can never exceed the user's own access.

Function Requires Why
OAuth application setup Entra ID admin account Creates the App Registration and grants permissions
File upload destination Runtime user session Delegated tokens act within that specific user's own OneDrive

4. The Most Common Confusion in Organizations

Many teams mistakenly think:

"We updated the client secret in ServiceNow, but OneDrive still uploads into the wrong user's folder."

This happens because, under the delegated model:

  • The Entra ID credentials control the application's identity and permissions.
  • The Microsoft session of whoever last completed the OAuth consent ("Get OAuth Token") flow controls which OneDrive the files actually land in.

Rotating a client secret doesn't touch the second part at all — the upload destination is tied to whichever user's session generated the currently-held delegated token, and that can silently be a different person than whoever the team assumes "owns" the integration.

5. The Alternative: Application Permissions (No Second Identity Required)

This is the option worth strongly considering if the delegated model's session-dependent behavior has already caused confusion, or if a predictable, admin-controlled upload destination matters more than convenience of setup.

Microsoft Graph also supports application permissions (via the OAuth Client Credentials grant), where the app acts under its own identity — no signed-in user involved at all. With application permissions like Files.ReadWrite.All, the target user or site is specified explicitly in the API path (for example, /users/{userPrincipalName}/drive or /sites/{siteId}/drive), rather than being implicitly determined by whoever's session token happens to be active.

This directly eliminates the confusion described in Section 4: there's no "whoever clicked Get OAuth Token" ambiguity, because the destination isn't session-dependent at all — it's whatever your integration explicitly specifies, every time, consistently.

The tradeoff: application permissions are broader by nature — a permission like Files.ReadWrite.All at the application level can potentially reach any user's files in the organization, so admin consent and scope review matter more here, not less. Microsoft's own Sites.Selected permission (which now supports application mode) is worth knowing about specifically because it lets you restrict an application's access to specific sites/document libraries rather than granting organization-wide reach — a meaningfully safer middle ground for a ServiceNow integration that only needs to write to one specific document location.

6. Summary and Recommendation

If you're already using the delegated model:

  • Use the Entra ID admin account only for configuring the OAuth application.
  • Use a specific, intentionally-chosen runtime account to generate the OAuth token ServiceNow will hold — and treat "which account last authenticated" as a piece of configuration worth documenting explicitly, not something to leave implicit.

If predictable, admin-controlled file destination matters more than initial setup simplicity — which is true for most enterprise document-management use cases — application permissions, scoped down with Sites.Selected where possible, avoids the two-identity confusion entirely rather than just managing around it.

Both models are valid Microsoft Graph architectures. The choice isn't "which is correct" — it's which tradeoff fits your integration: delegated is simpler to reason about for a single user's personal files, while application permissions trade broader scope for eliminating the exact session-dependent ambiguity that causes the most common support confusion described above.

Friday, June 20, 2025

Getting Started – PowerShell + ServiceNow Table API with Authentication

Introduction

ServiceNow's Table API provides full CRUD access to any record in the platform. Combine that with PowerShell, and you unlock the ability to automate ticketing, compliance tracking, CMDB updates, and more — right from the command line.

In this article, you'll learn how to:

  • Authenticate using Basic Auth, OAuth2 password grant (and why to avoid it), and OAuth2 Client Credentials grant (the current recommended approach)
  • Make your first Table API call from PowerShell
  • Parse and handle JSON responses
  • Set the stage for advanced integration in later posts

1. Basic Authentication Setup

This is the simplest approach, but it's not recommended for production. Basic Auth sends credentials with every single request, which is why it's generally treated as a legacy pattern for anything beyond quick local testing.

# Replace with your instance and credentials
$instance = "dev12345"
$user = "admin"
$pass = "your_password"
$base64Auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$user`:$pass"))

# Define headers and URL
$headers = @{
    "Authorization" = "Basic $base64Auth"
    "Accept"        = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"

# Call the API
$response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers

# Output the result
$response.result

⚠️ Tip: Avoid hardcoding passwords, even for quick testing. Basic Auth is fine for a five-minute experiment against a Personal Developer Instance — don't build anything real on top of it.

2. OAuth2 Password Grant — and Why to Avoid It for New Work

This is the grant type shown in most older ServiceNow + PowerShell tutorials, including earlier drafts of this one. It's worth understanding, but it's no longer the right choice for anything new:

Prerequisites:

  • OAuth enabled in ServiceNow
  • A registered app with Client ID and Client Secret
  • A user account with API access
# Credentials and endpoint
$clientId = "your_client_id"
$clientSecret = "your_client_secret"
$username = "admin"
$password = "your_password"
$instance = "dev12345"
$tokenUrl = "https://$instance.service-now.com/oauth_token.do"

# Build request body
$body = @{
    grant_type = "password"
    client_id = $clientId
    client_secret = $clientSecret
    username = $username
    password = $password
}

# Get token
$response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$accessToken = $response.access_token

# Make Table API request
$headers = @{
    "Authorization" = "Bearer $accessToken"
    "Accept"        = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"
$data = Invoke-RestMethod -Uri $url -Method Get -Headers $headers

$data.result

Why this isn't actually the secure upgrade it looks like: this is the Resource Owner Password Credentials ("password") grant — and it's explicitly deprecated per current OAuth 2.0 security guidance, not just an older option among equals. Notice that it still requires the literal user password in the request body, which means switching from Basic Auth to this grant type doesn't actually solve the "avoid hardcoding passwords" problem — it just moves the same password from a request header into a request body. If you're on an older instance that doesn't yet support the grant type below, this remains a working fallback. For anything new, use Client Credentials instead.

3. OAuth2 Client Credentials Grant (Recommended)

Available since the Washington DC release, this grant is purpose-built for exactly this scenario — a script or service authenticating as itself, with no specific human user's password involved at all.

Prerequisites:

  • OAuth enabled in ServiceNow
  • A registered application configured for the Client Credentials grant, with an associated OAuth Application User (a dedicated service account used as the identity context for the token — configure this with the "Web service access only" / "Internal Integration User" option so it can't log into the UI and isn't subject to normal password expiration policies)
  • On Zurich and later, register this through System OAuth > Application Registry > New Inbound Integration Experience > New Integration > OAuth – Client Credentials grant. On older releases, use Create an OAuth API endpoint for external clients instead — the underlying mechanism is the same, just a different registration screen.
# Credentials and endpoint — no username or password needed
$clientId = "your_client_id"
$clientSecret = "your_client_secret"
$instance = "dev12345"
$tokenUrl = "https://$instance.service-now.com/oauth_token.do"

# Build request body
$body = @{
    grant_type    = "client_credentials"
    client_id     = $clientId
    client_secret = $clientSecret
}

# Get token
$response = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
$accessToken = $response.access_token

# Make Table API request
$headers = @{
    "Authorization" = "Bearer $accessToken"
    "Accept"        = "application/json"
}
$url = "https://$instance.service-now.com/api/now/table/incident?sysparm_limit=1"
$data = Invoke-RestMethod -Uri $url -Method Get -Headers $headers

$data.result

Notice what's missing compared to the password grant: no username, no password. The script authenticates as the registered application itself, using the Client ID and Client Secret only. The Client Secret is still a credential worth protecting properly — that part of the "avoid hardcoding secrets" advice still applies, and we'll cover secure secret handling in Part 4 — but you're no longer storing an actual human user's password anywhere in the integration at all, which meaningfully reduces what's at risk if the script or its configuration ever leaks.

4. What You Should See

A single incident record, structured in JSON, regardless of which authentication method above you used:

{
  "result": [
    {
      "number": "INC0010001",
      "short_description": "Sample Incident",
      "state": "1",
      "sys_id": "abc123..."
    }
  ]
}

Conclusion

Connecting PowerShell to ServiceNow via the Table API is a powerful step toward automation. Whether you're managing incidents, risks, or CMDB items, understanding authentication methods — and which ones are actually current — is key. Basic Auth is fine for a quick local test; the password grant still works but is on its way out; Client Credentials is the one worth building on for anything you intend to keep running.

In future articles, we'll make this integration enterprise-grade with error handling, secure credential storage, and better performance.