> 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
