How to create or get MS Graph API access token in Laravel

Microsoft Graph API OAuth 2.0 authorization - Get Access Token


In this article, you will be learning how to get MS Graph API access token in Laravel using Microsoft Graph APIs step by step.

So before getting started with creating or getting the access token from MS Graph API, Install or create the authentication in Laravel and then get started.

Note: before getting started please get your Microsoft Client ID and Client Secret. Click here to get

You will also learn, how to Refresh the access_token and how to get the Profile Detail in Laravel at Step 5.


Step 1: Provide the credentials in .env file

APP_URL=http://localhost:8000
SPA_URL=http://localhost:3000

MICROSOFT_CLIENT_ID="XXXXX-XXXX-XXXX-b579-aXXXX0cae641"
MICROSOFT_CLIENT_SECRET="vnCXX~XXXXXXXXXXXXX.zXMXoawEuFYQDCCCCCCCXXXXXXXXX"
MICROSOFT_REDIRECT_URI="${SPA_URL}/auth/microsoft/callback" # (On Javascript Application - Vue,React,Angular,etc)
# MICROSOFT_REDIRECT_URI="${APP_URL}/v1/ms-graph/microsoft/callback" # (On Laravel Application)
MICROSOFT_TENANT_ID="common"
MICROSOFT_LOGOUT_REDIRECT_URI="${SPA_URL}"  # (On Javascript Application - Vue,React,Angular,etc)
# MICROSOFT_LOGOUT_REDIRECT_URI="${APP_URL}" # (On Laravel Application)


Step 2: Create a migration to store Microsoft Graph Token

Create migration using artisan command:

php artisan make:migration create_ms_graph_tokens_table

After successfully creating the migration, let's open ms_graph_tokens file from the following path: "database /migrations /2024_01_07_100005_create_ms_graph_tokens_table.php" 

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ms_graph_tokens', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('token_type');
            $table->mediumText('access_token');
            $table->mediumText('refresh_token')->nullable();
            $table->integer('expires_in')->nullable(); // in seconds
            $table->timestamp('expiry_time')->nullable();
            $table->mediumText('authorization_code');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('ms_graph_tokens');
    }
};

Let's migrate the table using the following command:

php artisan migrate


Step 3: Create a Model

php artisan make:model MsGraphToken

Open MsGraphToken.php file and paste the below code:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class MsGraphToken extends Model
{
    use HasFactory;

    protected $table = 'ms_graph_tokens';

    protected $fillable = [
        'user_id',
        'token_type',
        'access_token',
        'refresh_token',
        'expires_in',
        'expiry_time',
        'authorization_code',
    ];
}

Now open User.php Model from the following path: "app/ Models/ User.php" and paste the below given relationship.

use App\Models\MsGraphToken;
class User extends Authenticatable
{
    // ... your existing code

    public function msGraphToken()
    {
        return $this->hasOne(MsGraphToken::class, 'user_id', 'id');
    }
}


Step 4: Create a Controller named MsGraphAuthController and paste the below code

php artisan make:controller MsGraphAuthController

After success creating the controller, open the MsGraphAuthController.php file from path: "app/ Http/ Controllers/ MicrosoftGraphAuthController.php"

<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\MsGraphToken;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;

class MsGraphAuthController extends Controller
{
    public function redirectToMicrosoft()
    {
        // Redirect the user to Microsoft login page for authentication
        $redirectUrl = 'https://login.microsoftonline.com/' . env('MICROSOFT_TENANT_ID') . '/oauth2/v2.0/authorize?client_id=' . env('MICROSOFT_CLIENT_ID') . '&redirect_uri=' . urlencode(env('MICROSOFT_REDIRECT_URI')) . '&response_type=code&scope=' . urlencode('openid profile email offline_access https://graph.microsoft.com/.default');
        return response()->json(['redirectUrl' => $redirectUrl]);
    }

    public function handleMsCallback(Request $request)
    {
        // Extract the authorization code from the request
        $authorizationCode = $request->code;

        // Make a request to exchange the authorization code for an access token
        $response = Http::asForm()->post('https://login.microsoftonline.com/'.env('MICROSOFT_TENANT_ID').'/oauth2/v2.0/token', [
            'client_id' => env('MICROSOFT_CLIENT_ID'),
            'client_secret' => env('MICROSOFT_CLIENT_SECRET'),
            'code' => $authorizationCode,
            'redirect_uri' => env('MICROSOFT_REDIRECT_URI'),
            'grant_type' => 'authorization_code',
        ]);

        $tokenResponse = $response->json();

        if ($response->json('access_token')) {

            $tokenResponse = $response->json();
            $tokenType = $response->json('token_type');
            $accessToken = $response->json('access_token');
            $refreshToken = $response->json('refresh_token');
            $expiresIn = $response->json('expires_in');
            $expiryTime = Carbon::now()->addSeconds($expiresIn);

            MsGraphToken::create([
                'user_id' => auth()->user()->id,
                'token_type' => $tokenType,
                'access_token' => $accessToken,
                'refresh_token' => $refreshToken,
                'expires_in' => $expiresIn,
                'expiry_time' => $expiryTime,
                'authorization_code' => $authorizationCode,
            ]);

            return response()->json([
                        'status' => 'success',
                        'message' => 'MsGraph Token Authentication successful'
                    ], 200);

        }else{

            return response()->json([
                    'status' => 'error',
                    'message' => 'Something went wrong: MsGraph Token Authorization Code',
                    'data' => $tokenResponse,
                ], 200);
        }
    }

    public function signOut()
    {
        $msAccessTokenData = MsGraphToken::where('user_id', auth()->id())->first();
        $msAccessTokenData->delete();

        $redirectUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=' . env('MICROSOFT_LOGOUT_REDIRECT_URI');
        return response()->json(['redirectUrl' => $redirectUrl]);
    }
}


Step 5: Create a Controller named MsGraphController.php and paste the below code

<?php

namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Models\MsGraphToken;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;

class MsGraphController extends Controller
{
    public function profile()
    {
        $user = Auth::user();
        $userProfileResponse = Http::withToken($user->msGraphToken->access_token)->get('https://graph.microsoft.com/v1.0/me');

        if ($userProfileResponse->json('mail') > '') {
            $response = $userProfileResponse->json();
            return response()->json([
                'message' => 'Profile fetched',
                'data' => $response,
            ], 200);
        }
    }

    public function checkIsAccessTokenExpired()
    {
        $user = Auth::user();
        if($user->msGraphToken){

            // Check if the access token is expired
            if (strtotime($user->msGraphToken->expiry_time) < time()) {

                // Access token is expired, refresh token
                $refreshToken = $user->msGraphToken->refresh_token;

                $newAccessToken = Http::asForm()->post('https://login.microsoftonline.com/'.env('MICROSOFT_TENANT_ID').'/oauth2/v2.0/token', [
                                        'client_id' => env('MICROSOFT_CLIENT_ID'),
                                        'client_secret' => env('MICROSOFT_CLIENT_SECRET'),
                                        'refresh_token' => $refreshToken,
                                        'grant_type' => 'refresh_token',
                                    ]);

                if($newAccessToken->successful()){

                    // Update the database with the new access token
                    MsGraphToken::where('user_id', Auth::user()->id)->update([
                        'access_token' => $newAccessToken['access_token'],
                        'refresh_token' => $newAccessToken['refresh_token'],
                        'expires_in' => $newAccessToken['expires_in'],
                        'expiry_time' => Carbon::now()->addSeconds($newAccessToken['expires_in']),
                    ]);

                    return response()->json([
                        'message' => 'New Authentication Successful',
                        'data' => 'token_validated',
                    ]);

                }else{

                    return response()->json([
                        'message' => 'Something Went Wrong!. Refresh Token',
                        'data' => 'invalid_refresh_token',
                        'status' => 'error',
                        'error' => 'error',
                    ]);
                }

            }else{

                return response()->json([
                    'message' => 'Authentication successful',
                    'data' => 'token_validated',
                ]);
            }

        }else{

            return response()->json([
                'error' => 'access_token_not_configured',
                'data' => 'access_token_not_configured',
                'message' => 'Microsoft configuration not completed',
            ]);
        }
    }
}


Step 6: Create a Route API in routes/api.php

use App\Http\Controllers\MsGraphAuthController;
use App\Http\Controllers\MsGraphController;

Route::prefix('v1/ms-graph')->group( function () {

    Route::get('/microsoft', [MsGraphAuthController::class, 'redirectToMicrosoft']);
    Route::post('/microsoft/callback', [MsGraphAuthController::class, 'handleMsCallback']);
    Route::get('/microsoft/logout', [MsGraphAuthController::class, 'signOut']);

    Route::get('/profile', [MsGraphController::class, 'profile']);
    Route::get('/auth-check', [MsGraphController::class, 'checkIsAccessTokenExpired']);
});


That's it. you are ready to use this functionality to get Microsoft Access Token and use it as per your requirement in the frontend application like Vue Js, React Js, Angular, Nuxt, etc.