Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

anasahmed700's avatar

Replace client secret with self-signed certificate to authenticate Azure AD in PHP Laravel

I am currently using the following PHP code in Laravel to authenticate and obtain an embed URL for Power BI reports. However, I would like to enhance the security of my Azure AD app by replacing the current client secret-based authentication with a self-signed certificate.

Here is my current code which is working with client secret.

<?php

namespace App\Http\Controllers;

use App\Models\MenuTool;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class PowerBIController extends ApiController
{
    private function getAccessToken()
    {
        $response = Http::asForm()->post("https://login.microsoftonline.com/" . env('PBI_TENANT_ID') . "/oauth2/v2.0/token", [
            'grant_type' => env('PBI_GRANT_TYPE'),
            'client_id' => env('PBI_CLIENT_ID'),
            'client_secret' => env('PBI_CLIENT_SECRET'),
            'scope' => env('PBI_SCOPE'),
        ])->body();

        return $response;
    }

    private function generatePowerBIToken($group_id, $report_id)
    {
        $token = json_decode($this->getAccessToken())->access_token;

        $token_response = Http::asForm()
            ->withHeaders([
                'Content-Type' => 'application/x-www-form-urlencoded',
                'Authorization' => 'Bearer ' . $token,
            ])
            ->post("https://api.powerbi.com/v1.0/myorg/groups/" . $group_id . "/reports/" . $report_id . "/GenerateToken", [
                'grant_type' => env('PBI_GRANT_TYPE'),
            ]);
        $embed_response = $this->getEmbedUrl($token, $group_id, $report_id);
        return ["token" => $token_response->json()['token'], "report_id" => $embed_response['id'], 'embed_url' => $embed_response['embedUrl']];
    }

    private function getEmbedUrl($token, $group_id, $report_id)
    {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $token,
        ])
            ->get("https://api.powerbi.com/v1.0/myorg/groups/$group_id/reports/$report_id");
        return $response->json();
    }

    public function index($lang, $slug)
    {
        try {
            $menu = MenuTool::where('slug', $slug)->where('lang', $lang)->first();
            
            if ($menu) {
                if (auth()->user()->isClient()) {
                    $product_ids = array_column(auth()->user()->client->products->toArray(), "id");
                    if (in_array($menu->product_id, $product_ids)) {
                        $token = $this->generatePowerBIToken($menu->group_id, $menu->report_id);
                        return $this->successResponse($token);
                    }

                    return $this->errorResponse("Forbidden", 403);
                } else {
                    $token = $this->generatePowerBIToken($menu->group_id, $menu->report_id);
                    return $this->successResponse($token);
                }
            }
            return $this->errorResponse("Report not found", 404);
        } catch (\Throwable $th) {
            return $this->errorResponse($th->getMessage(), 500);
        }
    }
}

I have already created a self-signed certificate and uploaded it to my Azure AD app. Now, I am struggling with the integration of the certificate-based authentication into the existing code.

Could someone please provide guidance or a code snippet on how to modify the existing code to use the self-signed certificate for authentication instead of the client secret? Any additional steps or considerations for working with certificates in this context would be greatly appreciated.

Thank you in advance!

0 likes
0 replies

Please or to participate in this conversation.