Skip to main content

Azure App Registration: A Complete Guide from Zero to Working App

Nitin Kumar Singh
Author
Nitin Kumar Singh
I build enterprise AI solutions and cloud-native systems. I write about architecture patterns, AI agents, Azure, and modern development practices — with full source code.
Table of Contents

If you have ever tried to call the Microsoft Graph API, integrate with SharePoint, or add “Sign in with Microsoft” to an application, you hit the same wall: you need an App Registration. It is the first thing you do, and if you get it wrong, nothing else works.

This article is everything you need to know about App Registration — what it actually creates, the different application types, how authentication flows differ between them, when to use a secret versus a certificate, what “Expose an API” means, and how tokens fit together. The next article covers the permissions model in detail.


What Azure App Registration Actually Creates
#

Azure Active Directory (now called Microsoft Entra ID, though the old name still appears everywhere in portal and docs) is Microsoft’s cloud identity provider. It handles authentication and authorization for Microsoft 365, Azure, and any application you register with it.

When you register an application, Azure AD creates two things:

  1. Application object — the global definition of your app, stored in the tenant where you registered it. This is what you manage in the portal.
  2. Service principal — an instance of that application in a specific tenant. Think of the application object as the class and the service principal as the instance. In single-tenant apps they are in the same tenant; in multi-tenant apps a service principal is created in every tenant where a user consents.

You interact almost entirely with the application object. The distinction matters when troubleshooting permission grants and consent.


Before You Register: Four Questions
#

1. What type of app is this? Web app (server-side), SPA (browser-only), mobile/desktop, or background service? This determines the authentication flow.

2. Who will sign in? Only people in your organization (single tenant), people in any Azure AD tenant (multi-tenant), or also personal Microsoft accounts?

3. Does the app call APIs on behalf of a user, or on its own? Delegated (acting as the user) vs application (acting as itself). This determines permission type.

4. Does this app expose its own API for others to call? If yes, you need to define scopes under “Expose an API.”


Registering Your First App
#

Step 1 — Open App Registrations
#

Go to portal.azure.com → search App registrationsNew registration.

App Registration Search

Step 2 — Fill in the Registration Form
#

![New App Registration Form](/img/posts/new-app-registration.png)

Name — internal display name. End users see it on consent screens and in their app access lists under myapps.microsoft.com.

Supported account types — three options:

OptionWhat it meansUse when
Accounts in this organizational directory onlySingle-tenant. Only your Azure AD tenantInternal tools, intranet apps
Accounts in any organizational directoryMulti-tenant. Any Azure AD tenant can sign inSaaS products sold to businesses
Accounts in any org directory + personal accountsMulti-tenant + personal MSAConsumer-facing apps (Outlook.com users, Xbox, etc.)

You can change this later in the manifest if needed, but it has implications for token issuers, so choose correctly upfront.

Redirect URI — where Azure AD sends the user after authentication. Optional at registration time, but you must add one before your app can complete a sign-in. Covered in detail below.

Step 3 — Register
#

Click Register. Azure creates the app and takes you to its Overview blade.

App Overview

The Three IDs You Need
#

IDWhat it isWhere you use it
Application (client) IDUnique identifier for your appclient_id in every auth request
Directory (tenant) IDYour Azure AD tenantToken endpoint URL, single-tenant token requests
Object IDInternal Azure object IDMicrosoft Graph calls to manage the app itself

The client ID and tenant ID go into your application config immediately. Store them as config values, not hardcoded strings.


Application Types and Authentication Flows
#

The type of application determines which OAuth 2.0 flow to use and whether your app can keep a secret. This is the most important concept to get right.

Confidential Clients vs Public Clients
#

Confidential clients can securely hold a secret — they run on a server you control (web apps, APIs, background services). The client secret or certificate never leaves your server.

Public clients cannot hold a secret — they run in environments you do not fully control (browsers, mobile apps, desktop apps). Any secret embedded in a SPA JavaScript bundle or a mobile APK is extractable.

Web Application (Confidential Client)
#

A traditional server-side web app — ASP.NET Core MVC, Next.js with a Node backend, Django, etc.

Flow: Authorization Code flow (with or without PKCE, though PKCE is good practice even for confidential clients).

  1. User visits your app, is redirected to Azure AD login
  2. User authenticates, Azure AD redirects back to your redirect URI with an authorization code
  3. Your server exchanges the code for tokens using the client secret or certificate
  4. Tokens stay on the server; the browser never sees them

Platform to select in portal: Web

Requires secret or certificate: Yes — the server-side exchange needs to prove it is your app.

Redirect URI format: https://yourapp.com/auth/callback — must be HTTPS in production; http://localhost:PORT/auth/callback is allowed for development.

Single Page Application — SPA (Public Client)
#

A browser-only frontend — React, Angular, Vue with no server-side backend, or a backend-for-frontend pattern where the browser itself gets tokens.

Flow: Authorization Code flow with PKCE (Proof Key for Code Exchange). The implicit flow (response_type=token) was deprecated in 2019 — do not use it.

PKCE replaces the client secret with a cryptographically random challenge generated per-request in the browser. There is nothing to steal from JavaScript bundles.

Platform to select in portal: Single-page application

Requires secret or certificate: No — PKCE handles it.

Redirect URI format: https://yourapp.com or http://localhost:4200 for Angular CLI dev server.

Authentication Blade

Mobile and Desktop Applications (Public Client)
#

Native apps — MAUI, WPF, WinForms, Electron, iOS, Android.

Flow: Authorization Code with PKCE. On Windows you can also use Windows Integrated Authentication (Kerberos) for seamless SSO in domain-joined environments.

Platform to select in portal: Mobile and desktop applications — pick the pre-built redirect URIs for MSAL:

  • https://login.microsoftonline.com/common/oauth2/nativeclient
  • msal{client-id}://auth (for iOS/Android)

Requires secret or certificate: No.

Daemon / Background Service (Confidential Client)
#

No user interaction. A scheduled job, Azure Function, microservice, or any process that needs to call an API as itself rather than on behalf of a user.

Flow: Client Credentials flow — no authorization code, no user, just a direct token request using the client ID plus secret or certificate.

POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={client-id}
&client_secret={client-secret}
&scope=https://graph.microsoft.com/.default

The .default scope means “request all application permissions that have been admin-consented for this app.”

Platform to select in portal: None — daemon apps do not need a platform/redirect URI configured.

Requires secret or certificate: Yes — this is the only authentication mechanism available.


Redirect URIs
#

A redirect URI is the endpoint Azure AD sends the authorization code (or tokens in legacy flows) to after authentication. Rules:

  • Must exactly match what your app registers. One character difference and authentication fails with AADSTS50011.
  • HTTPS required in production (localhost HTTP is allowed).
  • You can register up to 256 redirect URIs per app.
  • Wildcards are not allowed for web apps (they are allowed for mobile custom scheme URIs like myapp://auth*).

Refer to the above example for the redirect URI, we have added one local app URI.

Common mistake: Registering https://yourapp.com/callback but your app sends https://yourapp.com/callback/ (trailing slash). They are different URIs. Azure AD treats them as a mismatch.

Front-channel logout URL
#

Also on the Authentication blade. When Azure AD signs a user out of all sessions (e.g., user changes their password), it sends a GET to this URL to let your app clear its own session. Set it if your app maintains server-side sessions.


Credentials: Client Secrets and Certificates
#

Found under Certificates & secrets on the app blade.

Certificates & Secrets Blade

Client Secrets
#

A random string Azure generates (you cannot set your own). You copy it once when created — it is never shown again.

Add a secret: Certificates & secrets → Client secrets → New client secret → enter a description → pick expiry (6 months, 12 months, 18 months, 24 months, or Custom up to 24 months, unless your tenant policy allows longer).

// .NET — configure MSAL with a client secret
var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)      // from config, not hardcoded
    .Build();

Expiry is enforced. When a secret expires, every app using it stops authenticating. Set a calendar reminder when you create a secret — ideally automate rotation with Azure Key Vault references.

Never commit secrets to source control. Use environment variables, app settings, or Key Vault.

Certificates
#

A certificate is more secure than a secret for three reasons:

  • The private key never leaves your infrastructure (you upload only the public key certificate to Azure AD).
  • Stronger cryptography (RS256 or ES256 assertion signing).
  • Better audit trail — you can see which certificate was used.

How to use a certificate:

  1. Generate a self-signed certificate (or use one from your CA):

    openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
      -subj "/CN=MyAzureApp"
    openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passout pass:
  2. Upload cert.pem (the public key) to the Certificates tab in the portal.

  3. Store cert.pfx (the private key) in Azure Key Vault or your server’s certificate store.

// .NET — configure MSAL with a certificate from Key Vault
var credential = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(kvUri), credential);
var certBytes = Convert.FromBase64String(
    (await secretClient.GetSecretAsync("MyAppCert")).Value.Value);
var cert = new X509Certificate2(certBytes);

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithCertificate(cert)
    .Build();

Use certificates in production, secrets in development and CI pipelines. Managed Identity is even better where available — no credential to manage at all.

Federated Credentials (Workload Identity Federation)
#

A newer, better option for CI/CD and non-Azure workloads: your GitHub Actions workflow, Kubernetes pod, or Google Cloud workload presents a token from its own identity provider, and Azure AD trusts it without a secret or certificate.

If you are running pipelines in GitHub Actions, set up federated credentials instead of storing a client secret in GitHub Secrets.


Token Types
#

When your app authenticates, Azure AD returns tokens. Understanding what each one is for matters.

TokenAudienceLifetimePurpose
ID tokenYour app~1 hourProves who the user is. Contains user claims (name, email, object ID).
Access tokenThe API being called~1 hourProves the app is authorized to call an API. Contains scopes/roles.
Refresh tokenAzure AD24h–90 daysExchange for new access/ID tokens without user interaction. Only issued for delegated flows.

Your app should never validate or parse the access token if you are the client calling an API (e.g., calling Microsoft Graph). The access token is for Graph, not for you. The ID token is what your app uses to know who signed in.

If you are building an API that receives access tokens, you must validate them (signature, issuer, audience, expiry). MSAL and the ASP.NET Core middleware do this for you.


Expose an API
#

If your application is an API that other apps will call (not just a client that calls other APIs), you need to define scopes under Expose an API.

Expose an API

Application ID URI
#

A unique identifier for your API in the format api://{client-id}. You can change it to something readable like api://mycompanyapi, but the default is fine. Set it by clicking the “Set” link at the top of the Expose an API blade.

Defining Scopes
#

A scope represents a permission that client applications can request to access your API.

Click Add a scope and fill in:

FieldExampleNotes
Scope nameaccess_as_userNo spaces. Convention: lowercase with underscores.
Who can consentAdmins and usersChoose “Admins only” for sensitive operations.
Admin consent display nameAccess MyAPI as a userShown to admins on the consent screen.
Admin consent descriptionAllows the app to call MyAPI on behalf of the signed-in user.Be specific.
User consent display nameAccess MyAPIShown to users on the consent screen.

Client apps then request this scope as api://{client-id}/access_as_user.

Authorized Client Applications
#

You can pre-authorize specific client apps to use your API scopes without requiring user consent — useful for first-party clients that you own. Add their client ID and the scope.


Branding and Properties
#

Under Branding & properties:

  • Publisher domain — shown on consent screens. Verify your domain to replace the default *.onmicrosoft.com display with your own domain, which makes consent screens less alarming to users.
  • Logo — displayed on the consent screen and in myapps.microsoft.com.
  • Service terms / Privacy statement URLs — required if your app requests user consent at runtime.

The Manifest
#

The Manifest blade shows the raw JSON of the application object. Almost everything configurable in the portal blades is represented here. Occasionally you need to edit the manifest directly for properties that the portal does not expose:

  • "accessTokenAcceptedVersion": 2 — force v2 tokens (default for new apps, but older registrations may be v1).
  • "optionalClaims" — add extra claims to tokens (e.g., upn, auth_time, email).
  • "groupMembershipClaims": "SecurityGroup" — include group IDs in tokens for RBAC.
  • "requiredResourceAccess" — programmatically define API permissions (useful for IaC).

Multi-Tenant Applications
#

If you chose “Accounts in any organizational directory,” the sign-in endpoint changes. Use common or organizations instead of your tenant ID:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize

First-time sign-in from a new tenant triggers a consent prompt. The user (or admin) consents, and Azure AD creates a service principal in their tenant. After that, tokens work normally.

Admin consent URL for multi-tenant apps:

https://login.microsoftonline.com/{customer-tenant-id}/adminconsent
?client_id={your-client-id}
&redirect_uri={your-redirect-uri}

Send this URL to IT admins at customer organizations so they can grant consent org-wide without individual users being prompted.


Quick Reference: What Goes Where
#

ThingWhere to configure it
Redirect URIsAuthentication → platform section
Logout URLAuthentication → Front-channel logout URL
Client secretsCertificates & secrets → Client secrets
Certificate (public key)Certificates & secrets → Certificates
Federated credentialsCertificates & secrets → Federated credentials
API permissions your app needsAPI permissions
Scopes your API exposesExpose an API
App roles (RBAC for your app)App roles
Optional claims in tokensToken configuration or Manifest
Branding on consent screenBranding & properties
Raw JSON configManifest

What to Read Next#

The next article goes deep on permissions: the difference between delegated and application permissions, how admin consent works, how to read scope strings, common Graph scopes, and the impact on audit trails in SharePoint and Exchange.


Resources
#

Related

Implementing SharePoint File CRUD Operations using Microsoft Graph API

·11 mins
Introduction # Microsoft Graph API provides a unified endpoint for accessing Microsoft 365 services, including SharePoint. This article demonstrates how to implement create, read, update, and delete (CRUD) operations for files in SharePoint document libraries using Microsoft Graph API and .NET. You’ll learn how to authenticate to Microsoft Graph, navigate SharePoint site structure, and manage files programmatically.

.NET Architecture at Scale: Visual Guide to Modern Design Patterns

·46 mins
.NET Architecture at Scale: Visual Guide to Modern Design Patterns # ⚡ Performance Note: This article contains 16 comprehensive patterns with visual diagrams. For faster loading, consider bookmarking specific sections or using the “Find in Page” (Ctrl+F) feature to jump to relevant patterns.