Overview

The EGU Partner Portal provides secure external API access for authorized partners to retrieve turnaround report data programmatically using OAuth2 authentication.


How External Access Works

Authentication & Authorization Flow

┌─────────────────┐
│ External System │  1. Request Token
│   (Partner)     │────────────────────┐
└─────────────────┘                    │
                                       v
                              ┌────────────────┐
                              │   Azure AD     │
                              │  Validates:    │
                              │  - Credentials │
                              │  - Role        │
                              └────────┬───────┘
                                       │
                                       │ 2. Issues JWT Token
                                       │    - appid claim
                                       │    - ExternalSystem.Access role
                                       │    - 1 hour expiry
                                       v
┌─────────────────┐
│ External System │  3. Call API with Token
└────────┬────────┘
         │
         v
┌────────────────────────────┐
│  Partner Portal API        │
│                            │
│  ✓ JWT Validation          │
│  ✓ Role Check              │
│  ✓ Route Restriction       │
│  ✓ Company Authorization   │
│                            │
│  → Query Database          │
│  → Return JSON             │
└────────────────────────────┘

Security Layers

  1. Authentication: Azure AD validates credentials and issues signed JWT tokens
  2. Role Check: Only apps with ExternalSystem.Access role can authenticate
  3. Route Restriction: External tokens limited to /api/external/* endpoints
  4. Company Authorization: Apps can only access their assigned company data

Authentication

OAuth2 Configuration

ItemValue
Token URLhttps://login.microsoftonline.com/f90faace-b48d-4a19-a39c-1dd7b37686e3/oauth2/v2.0/token
Client ID

11a51e47-cee5-4bb6-882b-a669dfaf1cb8

Client SecretYOUR_CLIENT_SECRET
Grant Typeclient_credentials
Scopeapi://e85dc5b1-f01b-45bd-b48d-08f50ee2e160/.default
Content-Typeapplication/x-www-form-urlencoded

Token Request

POST https://login.microsoftonline.com/f90faace-b48d-4a19-a39c-1dd7b37686e3/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=11a51e47-cee5-4bb6-882b-a669dfaf1cb8
&client_secret=YOUR_CLIENT_SECRET
&scope=api://e85dc5b1-f01b-45bd-b48d-08f50ee2e160/.default

Response:

{
  "token_type": "Bearer",
  "expires_in": 3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGci..."
}

Token Lifetime: 1 hour



API Usage (Prod Environment)

Base Configuration

ItemValue
API Base URLhttps://apiservice.redbay-6992b142.swedencentral.azurecontainerapps.io/api/external
AuthenticationAuthorization: Bearer <token>
Content Typeapplication/json

Endpoint: Get Turnaround Report

Retrieves work order turnaround data with status transitions.

GET /turnaround-report

Query Parameters:

NameTypeRequiredDescriptionExample
companyNumberstringYesCompany identifierSonlincXML3
dateFromstringNoStart date (YYYY-MM-DD)2025-01-01
dateTostringNoEnd date (YYYY-MM-DD)2025-12-31

Request Example:

GET /api/external/turnaround-report?companyNumber=SonlincXML3&dateFrom=2025-01-01&dateTo=2025-12-31
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGci...
Accept: application/json

Response (200 OK):

{
  "turnaroundReportItems": [
    {
      "workOrderID": 1503,
      "workOrderNumber": "E261503",
      "workOrderTypeID": 1,
      "workOrderType": "New Installation",
      "consumptionCategoryID": 1,
      "consumptionCategoryName": "Apartment",
      "preFuseAmpere": 10,
      "preFuseTypeID": 1,
      "preFuseType": "Switch",
      "workOrderStatusID": 2,
      "workOrderStatus": "Registration Sent",
      "timestamp": "2025-12-20T10:30:00Z"
    }
  ]
}

Response Fields:

FieldTypeDescription
workOrderIDintegerWork order identifier
workOrderNumberstringWork order number
workOrderTypestringType (e.g., "New Installation")
consumptionCategoryNamestringCategory (e.g., "Apartment")
preFuseAmpereintegerPre-fuse amperage
preFuseTypestringPre-fuse type
workOrderStatusstringStatus (e.g., "Registration Sent")
timestampstringISO 8601 timestamp

HTTP Status Codes:

CodeDescription
200Success
400Invalid parameters (e.g., date range > 5 years)
401Missing or invalid token
403Not authorized for this company
500Server error

Validation Rules:

  • Date range max 5 years
  • dateFrom must be ≤ dateTo

Configuration

Azure AD Setup

  1. Define API App Role

    Before external systems can be granted access, an App Role must be defined in the API App Registration.

    Go to:

    • Microsoft Entra IDApp registrations

    • Open EGU.PartnerPortal.ApiService

    Navigate to App roles → Create app role.

    Configure the role:

    FieldValue
    Display nameExternal System Access
    Allowed member typesApplications
    ValueExternalSystem.Access
    DescriptionAllows external systems to access turnaround report data

    Save the role.

  2. Create External System App Registration

    • Create a separate application registration for each external company.

      Go to:

      • Microsoft Entra IDApp registrations

      • Select New registration

      Configuration:

      SettingValue
      Name{CompanyName}-PartnerPortal-Access
      Supported account typesAccounts in this organizational directory only
      Redirect URILeave blank
  3. Generate Client Secret

      1. Open the newly created {CompanyName}-PartnerPortal-Access app.

      2. Navigate to Certificates & secrets.

      3. Click New client secret.

      4. Copy the secret value immediately and store it securely.

      ⚠️ The secret value cannot be viewed again after creation.

      Never commit secrets to source control.

  4. Assign Permissions

    • Add permission: EGU.PartnerPortal.ApiService
    • Select: ExternalSystem.Access
    • Grant admin consent

  5. Company Mapping (API side configuration)

    {
      "ExternalCompanies": {
        "Ravdex": {
          "AppId": "11a51e47-cee5-4bb6-882b-a669dfaf1cb8",
          "CompanyNumber": "YOUR_COMPANY_NUMBER",
          "Name": "Ravdex"
        }
      }
    }
  • No labels