<?php
namespace App\Authentication;
use CodeIgniter\Shield\Authentication\Authenticators\AbstractAuthenticator;
use League\OAuth2\Client\Provider\Generic; // Or a Microsoft-specific provider if available
class MicrosoftAuthenticator extends AbstractAuthenticator
{
public function attempt(array $credentials = null)
{
$provider = new Generic([
'clientId' => env('MICROSOFT_CLIENT_ID'), // Get these from your .env file
'clientSecret' => env('MICROSOFT_CLIENT_SECRET'),
'redirectUri' => 'https://your-domain.com/auth/microsoft/callback', // Your callback URL
'urlAuthorize' => 'https://login.microsoftonline.com/' . env('MICROSOFT_TENANT_ID') . '/oauth2/v2.0/authorize',
'urlAccessToken' => 'https://login.microsoftonline.com/' . env('MICROSOFT_TENANT_ID') . '/oauth2/v2.0/token',
'urlResourceOwnerDetails' => 'https://graph.microsoft.com/v1.0/me', // Or another endpoint for user details
]);
// Authorization URL
if (!isset($_GET['code'])) {
$authorizationUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState(); // Store state in session for verification
header('Location: ' . $authorizationUrl);
exit;
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
// Try to get an access token (using the authorization code grant)
try {
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// Get user details
$user = $provider->getResourceOwner($token);
// Now you have the user details from Microsoft.
// You'll need to find or create a user in your database
// based on the information provided by Microsoft (e.g., email address).
$userModel = model('UserModel'); // Your user model
$existingUser = $userModel->where('email', $user->getEmail())->first(); // Example: Find user by email
if ($existingUser) {
// User exists, log them in
$this->login($existingUser);
return true;
} else {
// User doesn't exist, create a new user
$newUser = [
'email' => $user->getEmail(),
'username' => $user->getName(), // Or generate a username
// ... other user data ...
'password_hash' => password_hash(random_string('alnum', 16), PASSWORD_DEFAULT) // You'll need a password, even for OAuth users.
];
$userId = $userModel->insert($newUser);
if($userId){
$newUser['id'] = $userId;
$this->login($newUser);
return true;
}else{
return false;
}
}
} catch (\Exception $e) {
exit('Something went wrong: ' . $e->getMessage());
}
}
}
// ... other methods (logout, validate, etc.)
}