Comments (4)
Hey! Have you figured a solution for this? I'm encountering the same issue. Thank you in advance!
from oauth2-azure.
Worth checking that the userid you are using at login is the same user principal name you used when registering the app (and hence the user name associated with the client id). Perhaps the authorization server finds a mismatch and says (in effect) 'try again' instead of bouncing the login with an error message.
from oauth2-azure.
Some issues with the code are that you are saving a token string and in " $token = $_SESSION['token']??null;" expecting a token object back. Saving the whole token object did not work for me. I found you need to save the serialized token in the session if you want to use the token outside of the authorization page.
////////////////////////
// following is login logic
$envPath = "" // TODO put in path to your env file
$redirect_uri = ""; // TODO put in your page url
$microsoft_connector = new MicrosoftConnector($envPath, $redirect_uri);
if (!isset($_GET['code'])) {
// If we don't have an authorization code, get one
$authUrl = $microsoft_connector->getProvider()->getAuthorizationUrl();
$_SESSION['oauth2state'] = $microsoft_connector->getProvider()->getState();
header('Location: ' . $authUrl);
exit;
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
// State validation
unset($_SESSION['oauth2state']);
//log 'MS Auth possible CSRF'
header("Location: " . $homeDir); // try to reset urls to remove obsolete codes.
exit();
} else {
// Now you have a token you can look up a users profile data
try {
// Try to get an access token (using the authorization code grant)
$token = $microsoft_connector->getTokenWithCode($_GET['code']); // also saves serialized token to session.
$user = $microsoft_connector->getUserDetails($token);
$full_name = $user['displayName'];
$email = $user['userPrincipalName'];
// TODO sign in or register the user as appropriate.
} catch (Exception $e) {
// Failed to get user details
// log "There was an error in ms auth: " . $e->getMessage()
exit('Unexpected error:' . $e);
}
}
//////////////////////
// to create a test calendar entry on another PHP page after user is signed in.
$microsoftConnector = new MicrosoftConnector($dbPath, $redirect_uri);
//$token = $microsoftConnector->recreateAccessTokenFromSession(); // works if done soon after login.
$token = $microsoftConnector->getTokenFromSession();
$event_array = $microsoftConnector->createTestEvent();
$eventId = $microsoftConnector->createEvent($event_array, $token);
from oauth2-azure.
this code works for me:
<?php declare(strict_types=1);
define( 'ROOT', __DIR__ . '/' );
define( 'NO_AUTH', true );
require "./inc/global.inc.php";
require "./inc/user-check.php";
define( 'MSONLINE_URL', 'https://login.microsoftonline.com/' );
define( 'MSGRAPH_SCOPE', 'https://graph.microsoft.com/User.Read' );
define( 'MSGRAPH_URL', 'https://graph.microsoft.com/v1.0/me/' );
define( 'REDIRECT_URL', 'https://' . $_SERVER['SERVER_NAME'] . '/' . basename( $_SERVER['SCRIPT_FILENAME'] ) );
$_SESSION['state'] = session_id();
if( array_key_exists( 'error', $_POST ) ) {
LOG->critical( 'Received error ', $_POST );
http_response_code( 500 );
exit();
}
if( array_key_exists( 'action', $_GET ) ) {
LOG->debug( 'Logon action: ', $_GET );
switch($_GET['action']) {
default:
LOG->critical( 'Unknown action: ', [ 'action' => $_GET['action'] ] );
case 'login':
requestAzureAdCode();
exit;
case 'logout':
LOG->notice( 'Logout' );
session_destroy();
$logout_url = MSONLINE_URL . SETTINGS['aad']['tennant-id'] . "/oauth2/v2.0/logout?post_logout_redirect_uri=https://sbw-media.ch";
header( 'Location: ' . $logout_url );
exit;
}
}
/**
* received an authorization code from Azure AD
* use this to
* 1) redeem this code for an access token
* 2) use the Bearer access token for Graph and get user info (most importantly Object-ID)
* 3) store user info in session
* 4) load the associated user from the Zeugnis DB
* if this user object-id is not known to us send a 403, unset session
* 5) redirect to index.php
*/
if( array_key_exists( 'code', $_POST ) ) {
LOG->debug( 'Got authorization code', [ 'state' => $_POST['state'], 'session_state' => $_POST['session_state'] ] );
/* get access token */
if( $access_token = getAccessToken( $_POST['code'] ) ) {
if( $resource = getUserResource( $access_token ) ) {
LOG->notice( 'AD User logged on', $resource );
$_SESSION['AD_upn'] = $resource["userPrincipalName"];
$_SESSION['AD_user'] = $resource["displayName"];
$_SESSION['AD_id'] = $resource["id"];
$_SESSION['AD_email'] = $resource["mail"];
if( !logon() ) {
session_unset();
LOG->alert( 'Forbidden 403', $resource );
header( 'HTTP/1.0 403 Forbidden' );
exit();
}
LOG->info( 'Redirect to /', $resource );
header( 'Location: /' );
exit();
}
LOG->critical( 'Graph failed', [ 'access token' => $access_token ] );
header( 'HTTP/1.0 403 Forbidden' );
}
LOG->critical( 'Missing code', $_POST );
header( 'HTTP/1.0 403 Forbidden' );
}
echo '<h1>Logon to sbw.edu</h1>';
echo '<p><a href="/hello.php?action=login"</a>Login</p>';
/**
* requestAzureAdCode
*
* @return void
*/
function requestAzureAdCode(): void
{
$params = [
'client_id' => SETTINGS['aad']['client-id'],
'scope' => MSGRAPH_SCOPE,
'redirect_uri' => REDIRECT_URL,
'response_mode' => 'form_post',
'response_type' => 'code',
'state' => $_SESSION['state'],
];
LOG->debug( 'Redirect to Azure AD authorizer' );
$login_url = MSONLINE_URL . SETTINGS['aad']['tennant-id'] . "/oauth2/v2.0/authorize";
header( 'Location: ' . $login_url . '?' . http_build_query( $params ) );
}
/**
* getUserResource from graph
*
* @param string $access_token
* @return array
*/
function getUserResource( string $access_token ): bool|array
{
LOG->debug( 'Getting user resource from Graph', [ 'access token' => shorten( $access_token, 15 ) ] );
/* get user info, using the access token as */
return sendGet( MSGRAPH_URL, [], 'Bearer ' . $access_token );
}
/**
* getAccessToken
* Only accept bearer type tokens
*
* @return string|bool
*/
function getAccessToken( string $authorization_code ): string|bool
{
LOG->debug( 'Get access token' );
/* Request token from Azure AD tokenizer */
$token_url = MSONLINE_URL . SETTINGS['aad']['tennant-id'] . "/oauth2/v2.0/token";
$params = [
'client_id' => SETTINGS['aad']['client-id'],
'client_secret' => SETTINGS['aad']['client-secret'],
'scope' => MSGRAPH_SCOPE,
'redirect_uri' => REDIRECT_URL,
'response_mode' => 'form_post',
'grant_type' => 'authorization_code',
'response_type' => 'code id_token offline_access',
'code' => $authorization_code,
'state' => $_SESSION['state'],
];
if( $answer = sendPost( $token_url, $params ) ) {
if( $answer['token_type'] !== 'Bearer' ) {
LOG->critical( "Wrong token type", $answer );
return false;
}
LOG->debug( 'New state: ', array_keys( $answer ) );
return $answer['access_token'];
}
return false;
}
/**
* logonZeugnis tool
* expects a $_SESSION['AD_id'] set to the Object ID of the user
*
* @return bool
*/
function logon(): bool
{
if( !isset( $_SESSION, $_SESSION['AD_id'] ) ) {
LOG->critical( 'No ObjectID' );
throw new InvalidArgumentException( 'No AD ObjectID found' );
}
// Search for the user in our database
return findUser( $_SESSION['AD_id'] );
}
/**
* Send a post request, return result in array
* @param string $url
* @param array $payload
*
* @return array|bool
*/
function sendPost( string $url, array $payload ): bool|array
{
$opts = [
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query( $payload )
]
];
$context = stream_context_create( $opts );
// we don-t want warnings, hence the @
if( $result = @file_get_contents( $url, false, $context ) ) {
$result = json_decode( $result, true );
if( !isset( $result['error'] ) ) {
return $result;
} else {
LOG->alert( $result['error_description'] );
exit;
}
}
LOG->alert( "sendPost: could not read response." );
exit;
}
/**
* Send a get request
*
* @param mixed $url
* @param mixed $payload
* @param mixed $authorization
* @return array
*/
function sendGet( string $url, array $payload, string $authorization ): array|bool
{
$opts = [
'http' => [
'method' => 'GET',
'header' => [
'Content-Type: application/x-www-form-urlencoded',
'Authorization: ' . $authorization
]
]
];
$context = stream_context_create( $opts );
// we don-t want warnings, hence the @
$result = @file_get_contents( $url . '?' . http_build_query( $payload ), false, $context );
if( $result = json_decode( $result, true ) ) {
return $result;
} else {
LOG->alert( $result );
return false;
}
}
from oauth2-azure.
Related Issues (20)
- Class "TheNetworg\OAuth2\Provider\Azure" not found HOT 1
- The Code_Verifier does not match the code_challenge supplied in the authorization request HOT 3
- Azure Graph is being deprecated in June 2023. Please use Microsoft Graph. HOT 3
- Client_credentials grant
- Firebase PHP-JWT key/algorithm type confusion HOT 1
- Question: what needs to be reachable through firewall?
- Not possible to set default algorithm HOT 2
- Uncaught Error: Firebase\JWT\JWT::decode(): Argument #3 ($headers) cannot be passed by reference HOT 16
- README sample incomplete
- Exception "The client_id / audience is invalid!" when using accesstoken HOT 8
- openssl_sign(): Supplied key param cannot be coerced into a private key HOT 1
- return in sample code
- Azure AD B2C issue
- Fatal error in getDefaultScopes() HOT 1
- Micorsoft Entra ID and msal-browser/2.37.1 error validation access token HOT 2
- Outdated CHANGELOG.md HOT 2
- Microsoft Graph suddenly not returning user profile attributes HOT 2
- V2 validateTokenClaims and AUD Prefix HOT 1
- phpmailer token HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from oauth2-azure.