> For the complete documentation index, see [llms.txt](https://docs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.akinon.com/technical-guides/instore/azure-oauth2-integration.md).

# Azure (Entra ID) OAuth2 Integration

This document describes the OAuth2 integration that allows enterprise users to sign in to InStore with single sign-on (SSO) through Azure Active Directory / Entra ID, along with the required configuration.

## <mark style="color:red;">How It Works</mark> <a href="#how-it-works" id="how-it-works"></a>

When a user selects "Sign in with Azure" in InStore, the standard OAuth2 Authorization Code flow is executed:

1. **Redirect** — The user is redirected to the Azure sign-in screen.
2. **Authentication** — The user signs in with their corporate Azure account.
3. **Callback** — Azure returns the user to the configured address with an authorization code.
4. **Token exchange** — InStore securely exchanges this code with Azure to obtain an access token.
5. **User info** — The user's email, first/last name, and store information are retrieved from Azure.
6. **Mapping & sign-in** — The user is mapped to the relevant store(s) in InStore, the staff record is created/updated, and the session is opened.

```
User                 InStore                    Azure Entra ID
   │                    │                            │
   │  Sign in w/ Azure  │                            │
   ├───────────────────▶│                            │
   │        Redirect to Azure login screen           │
   │◀────────────────────────────────────────────────
   │            Sign in with corporate account       │
   ├────────────────────────────────────────────────▶│
   │        Callback with code                        │
   │◀────────────────────────────────────────────────
   │                    │  Code → token exchange     │
   │                    ├───────────────────────────▶│
   │                    │  User info                  │
   │                    ├───────────────────────────▶│
   │   Sign-in success  │  Store mapping + session    │
   │◀───────────────────┤                            │
```

## <mark style="color:red;">What to Do on the Azure Side</mark> <a href="#azure-side" id="azure-side"></a>

An application registration is created via **Azure Portal → Entra ID → App registrations → New registration**, and the following details are prepared:

| Step                 | Description                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **App registration** | A new App Registration is created for InStore.                                                                              |
| **Redirect URI**     | InStore's post-login return address is added as `Web` type (must match exactly the address configured on the InStore side). |
| **Client secret**    | A client secret is generated under "Certificates & secrets".                                                                |
| **API permissions**  | Microsoft Graph → `User.Read` (read user profile).                                                                          |
| **User attributes**  | Email, first/last name, employee ID, and store information attributes must be populated in the directory.                   |

Once the registration is complete, note the following values to enter into InStore: **Application (client) ID**, **Directory (tenant) ID**, and the **client secret**.

## <mark style="color:red;">Configuration on the InStore Side</mark> <a href="#instore-configuration" id="instore-configuration"></a>

The following fields are entered for the Azure provider from the InStore management screen:

| Field                 | Description                                             | Example / Value                                                                                               |
| --------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Name**              | Provider name shown to the user                         | `Azure`                                                                                                       |
| **Slug**              | Provider identifier                                     | `azure`                                                                                                       |
| **Provider type**     | Type of service to connect to                           | `azure`                                                                                                       |
| **Icon**              | Logo on the login screen (png/jpg, max 128×128)         | Company logo                                                                                                  |
| **Client ID**         | Azure Application (client) ID                           | GUID                                                                                                          |
| **Client Secret**     | Azure client secret (stored encrypted)                  | —                                                                                                             |
| **Authorization URL** | Azure authorization endpoint                            | `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?...`                                        |
| **Token URL**         | Token exchange endpoint                                 | `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token`                                                |
| **Userinfo URL**      | User info endpoint (Microsoft Graph)                    | `https://graph.microsoft.com/v1.0/me?$select=mail,givenName,surname,employeeId,onPremisesExtensionAttributes` |
| **Redirect URL**      | Post-login return address (same as registered in Azure) | `https://<instore-address>/oauth/azure/callback`                                                              |
| **Is active**         | Whether the provider is in use                          | `true`                                                                                                        |

{% hint style="info" %}
Replace `{tenant}` with the **Directory (tenant) ID** obtained from Azure. The **Client Secret** is stored encrypted in InStore and is not shown back in the interface.
{% endhint %}

## <mark style="color:red;">User and Store Mapping</mark> <a href="#user-store-mapping" id="user-store-mapping"></a>

Below is an example response returned by Azure to the Userinfo URL (Microsoft Graph `/me`) call — the fields are limited by the `$select` in the configuration:

```json
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(mail,givenName,surname,employeeId,onPremisesExtensionAttributes)/$entity",
  "id": "8f4e2c1a-3b7d-4e9f-a1c2-5d6e7f8a9b0c",
  "mail": "ayse.yilmaz@firma.com",
  "givenName": "Ayşe",
  "surname": "Yılmaz",
  "employeeId": "10457",
  "onPremisesExtensionAttributes": {
    "extensionAttribute1": "IST001,IST002",
    "extensionAttribute2": null,
    "extensionAttribute3": null,
    "extensionAttribute4": null,
    "extensionAttribute5": null,
    "extensionAttribute6": null,
    "extensionAttribute7": null,
    "extensionAttribute8": null,
    "extensionAttribute9": null,
    "extensionAttribute10": null,
    "extensionAttribute11": null,
    "extensionAttribute12": null,
    "extensionAttribute13": null,
    "extensionAttribute14": null,
    "extensionAttribute15": null
  }
}
```

{% hint style="info" %}
Store (ERP) codes are kept as a comma-separated list in the extension attribute configured in the directory (`extensionAttribute1` in the example above).
{% endhint %}

The fields in this response are mapped to the InStore staff record as follows:

| InStore data | Source in Azure                                         |
| ------------ | ------------------------------------------------------- |
| Email        | User email (`mail`)                                     |
| First name   | `givenName`                                             |
| Last name    | `surname`                                               |
| Employee ID  | `employeeId`                                            |
| Store(s)     | Extension attribute — comma-separated store (ERP) codes |

### <mark style="color:red;">Mapping Rules</mark> <a href="#mapping-rules" id="mapping-rules"></a>

* Store codes are matched against store records in InStore. If no matching store is found, sign-in is rejected.
* If a staff member already exists with the email, their store assignments are updated; otherwise a new staff record is created with the default permission group.
* If the user is assigned to more than one store, the active store selection is managed through the InStore session, and all subsequent operations run in the context of the selected store (SSO continuity).

## <mark style="color:red;">Summary</mark> <a href="#summary" id="summary"></a>

* Enterprise users sign in to InStore with a single click using their Azure accounts.
* Passwords are not stored in InStore; authentication is handled entirely by Azure.
* User and store mapping is performed automatically.
* Setup is one-time: an app registration in Azure + provider configuration in InStore.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.akinon.com/technical-guides/instore/azure-oauth2-integration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
