How to get information about a user by having his token - php

How can I get some information about the user after his authorization, I need to get a list of his servers. I'm using RestCord and oauth2-discord-new libraries, but these libraries do not allow this. How to do this using php?
UPD:
What I tried:
$provider = $discord->provider;
if (!Yii::$app->request->get('code')) {
$options = [
'scope' => ['identify', 'email', 'guilds']
];
$authUrl = $provider->getAuthorizationUrl($options);
return $this->redirect($authUrl);
} else {
$token = $provider->getAccessToken('authorization_code', [
'code' => Yii::$app->request->get('code')
]);
$discord = new DiscordClient(['token' => $token->getToken()]);
$discord->user->getCurrentUser([]); // Return 401 UNAUTHORIZED
}

I looked at the source code of restcord. Also found there parameter tokenType. About it nothing is written in the documentation, but if you install it in OAuth then the library will work in user mode and not the bot. How to use it correctly:
$discord = new DiscordClient([
'token' => 'userToken',
'tokenType' => 'OAuth'
]);
I spent a lot of time looking for a solution to this problem, and I was very surprised that this parameter is not written in the official documentation. I hope this will save you time!

Related

Laravel 9 and Twilio Verify V2 "...must be of type array, string given" Error

I am setting up Twilio's Verify service to authenticate with a text number. The service works and sends a code to a cell phone, but when it gets to the verificationChecks part of the code, I receive the following error Twilio\Rest\Verify\V2\Service\VerificationCheckList::create(): Argument #1 ($options) must be of type array, string given, called in /Users/charles/Documents/Development/guard/app/Http/Controllers/Auth/RegisteredUserController.php on line 83.
If it helps, I am using the following tutorial on Twilio's site. And if you look at Twilio's API where their API still matches their tutorial document.
RegisteredUserController.php
...
protected function verify(Request $request)
{
$data = $request->validate([
'verification_code' => ['required', 'numeric'],
'phone_number' => ['required', 'string'],
]);
/* Get credentials from .env */
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio_sid = getenv("TWILIO_SID");
$twilio_verify_sid = getenv("TWILIO_VERIFY_SID");
$twilio = new Client($twilio_sid, $token);
$verification = $twilio->verify->v2->services($twilio_verify_sid)
->verificationChecks
->create($data['verification_code'], array('to' => $data['phone_number']));
if ($verification->valid) {
$user = tap(User::where('phone_number', $data['phone_number']))->update(['isVerified' => true]);
/* Authenticate user */
Auth::login($user->first_name());
return redirect()->route('home')->with(['message' => 'Phone number verified']);
}
return back()->with(['phone_number' => $data['phone_number'], 'error' => 'Invalid verification code entered!']);
}
...
The same issue just popped up for me over the weekend on code that I haven't touched in a very long time. I believe they updated something recently and the docs may be outdated. The docs show sending a string, while if you look at the actual vendor file, it is looking for an array now.
Try this:
$verification = $twilio->verify->v2->services($twilio_verify_sid)
->verificationChecks
->create(['code' => $data['verification_code'], 'to' => $data['phone_number']]);

How to register endpoint with Google RISC API in php

I've been reading and trying to implement what's instructed from the docs at Protect user accounts with Cross-Account Protection
What I've done so far as per below:
JWT::$leeway = 60;
$key = file_get_contents('location.json');
$time = time();
$payload = [
"iss" => "account email",
"sub" => "account email",
"aud" => "https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService",
"iat" => $time,
"exp" => $time + 3600,
];
/**
* IMPORTANT:
* You must specify supported algorithms for your application. See
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
* for a list of spec-compliant algorithms.
*/
$jwt = JWT::encode($payload, $key);
$decoded = JWT::decode($jwt, $key, ['HS256']);
print_r($jwt);
print_r($decoded);
$client = new Client();
try {
$request = $client->post('https://risc.googleapis.com/v1beta/stream:update', [
'headers' => [
'Authorization' => 'Bearer ' . $jwt,
'Accept' => 'application/json',
],
'form_params' => [
'delivery' => [
'delivery_method' => 'https://schemas.openid.net/secevent/risc/delivery-method/push',
'url' => 'https://test.myapp.com/webhooks/google',
],
'events_requested' => [
'https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked',
],
],
]);
$response = $request->getBody();
dd($response);
} catch (ClientException $exception) {
dd($exception->getResponse()->getBody()->getContents());
}
Issues I am facing:
I do not understand well how to use JWT from what I read in the docs, what am I doing wrong in my implementation?
The examples are in JAVA, but I need it in php and I tried reading the JAVA code but do not understand where several things are coming from.
From the much I've read, I assume I won't be able to test these events on local environment? That is point these events to be triggered on local? Or would services such as ultrahook allow doing so? Otherwise I would have to test the endpoint straight on server.
The error I get from the code above is Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
Trying the encoding suggested below RS256 gives me the error UnexpectedValueException: Algorithm not allowed I believe I do lack the necessary knowledge around JWT and doing something wrong there.
I'm also looking at how to do this cross-account protection from this link https://developers.google.com/identity/protocols/risc#java_1 I assume you are talking about this part (Generate an authorization token) https://developers.google.com/identity/protocols/risc#auth_token
I'm using php though but looking at the java code in the page it's using RS256 instead of HS256 in your code. If you use php then you can try firebase php and they have a simple JWT class you can use. https://github.com/firebase/php-jwt You can just use the example and replace the payload with yours then change to RS256. That's what I'm gonna try I can let you know if it works after.

Getting the Guild Roles for a User using Restcord and Wohali OAuth2 Discord Client

Need some help,
Using Wohali OAuth2 Client then Restcord to get actual content from the user logged.
But for some reason, i can't get it to list the roles for the user logged in.
Says "Message: There was an error executing the listGuildMembers command: Client error: GET https://discordapp.com/api/v6/guilds/{guild_id}/members?limit=1 resulted in a 401 UNAUTHORIZED response:"
The documentation is a bit lacking and i have spent a number of hours trying to get it sorted out.
use RestCord\DiscordClient;
$provider = new \Wohali\OAuth2\Client\Provider\Discord([
'clientId' => '{client_id}',
'clientSecret' => '{client_secret}',
'redirectUri' => '{redirect_uri}'
]);
$options = ['state' => 'CUSTOM_STATE', 'scope' => ['identify', 'email', 'guilds']];
if (!isset($_GET['code'])) {
// Step 1. Get authorization code
$authUrl = $provider->getAuthorizationUrl($options);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
// Step 2. Get an access token using the provided authorization code
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
}
$user = $provider->getResourceOwner($token);
$client = new DiscordClient(['token' => $token->getToken(), 'tokenType' => 'OAuth']);
$roles = $client->guild->listGuildRoles(['guild.id' => {guild_id}]);
var_dump($roles);
I have removed the clientId, secret, guild id and such but they are valid, since the example on auth from Wohali works and shows my info when logged in.
Thanks in advance for any tips / help / ideas.
You can view the response codes on the official discord docs:
https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#http-http-response-codes
401 means your token is bad/missing

Outlook - OAuth 2 - Fail to retrieve access token, grant_type=password is unsupported, only authorization_code and refresh_token are

I'm currently trying to implement a way to synchronize my PHP App calendar with the Outlook calendar of my clients, using Azure API.
I use OAuth2 and the custom Microsoft provider by Steven Maguire.
I currently run in an issue where I get an error in my response :
{"error":"unsupported_grant_type","error_description":"The provided value for the input parameter 'grant_type' is not valid. Expected values are the following: 'authorization_code', 'refresh_token'."}
I'm having trouble understanding why the grant_type password is not supported, even though it says on the documentation of Azure that it is.
The request looks like this :
client_id=44bef79b-**********************&client_secret=H****************&redirect_uri=https%3A%2F%2F192.168.1.123%2Fmapeyral%2Fcalendarsync.php&grant_type=password&username=******************&password=***********&scope=openid%20profile%20offline_access%20Calendars.ReadWrite
The Authorize url used is : https://login.live.com/oauth20_token.srf
as defined in the Steven Maguire provider.
The header contains the content-type application/x-www-form-urlencoded (I've seen a lot of post where this was what caused the error).
Some of my code :
$this->provider = new Microsoft([
'clientId' => MicrosoftGraphConstants::CLIENT_ID,
'clientSecret' => MicrosoftGraphConstants::CLIENT_SECRET,
'redirectUri' => MicrosoftGraphConstants::REDIRECT_URI,
'urlAuthorize' => MicrosoftGraphConstants::AUTHORITY_URL . MicrosoftGraphConstants::AUTHORIZE_ENDPOINT,
'urlAccessToken' => MicrosoftGraphConstants::AUTHORITY_URL . MicrosoftGraphConstants::TOKEN_ENDPOINT,
'urlResourceOwnerDetails' => MicrosoftGraphConstants::RESOURCE_ID,
'scope' => MicrosoftGraphConstants::SCOPES
]);
if ($_SERVER['REQUEST_METHOD'] === 'GET' && !isset($_GET['code']))
{
// Try getting access token from Database
$workingAccount = $GLOBALS['AppUI']->getState('working_account');
if (isset($workingAccount))
{
// DB access
$DB = new DatabaseConnection();
$dbAccess = $DB->getConnection();
$contactData = DBUserUtils::getContactDataFromEmail($GLOBALS['AppUI']->getState('working_account'), $dbAccess);
// If at least one user contact found
if (!is_null($contactData))
{
// If has refresh token => fill session variables using refresh token
if (!is_null($contactData['contact_refreshToken']))
{
log_msg('debug.log', 'Has refresh token');
$GLOBALS['AppUI']->setState('preferred_username', $contactData['contact_email']);
$GLOBALS['AppUI']->setState('given_name', $contactData['contact_first_name']." ".$contactData['contact_last_name']);
// Get new tokens
$newAccessToken = $this->provider->getAccessToken('refresh_token', [
'refresh_token' => $contactData['contact_refreshToken']
]);
// Update tokens and DB
$GLOBALS['AppUI']->setState('refresh_token', $newAccessToken->getRefreshToken());
$GLOBALS['AppUI']->setState('access_token', $newAccessToken->getToken());
DBOAuthUtils::updateTokenForUser($contactData['contact_id'], $GLOBALS['AppUI']->getState('refresh_token'), $dbAccess);
$this->redirectTo($redirectURL);
}
else
{
$this->getAccessToken();
}
}
else
{
$this->getAccessToken();
}
}
else
{
$this->getAccessToken();
}
function getAccessToken(){
$accessToken = $this->provider->getAccessToken('password', [
'username' => '*************',
'password' => '********',
'scope' => MicrosoftGraphConstants::SCOPES
]);
}
During the first try it doesn't pass the if (isset($workingAccount)) condition (as expected) and go straight to the last else.
Code is a bit ugly for now but I don't think it has an impact on my problem.
Any help would be appreciated !
Thanks
Edit : added code
That helped me, the problem was that I need to use Azure Active Directory and not Azure AD 2.0.
Problem solved !

Firebase REST access using PHP with Authentication

I'm trying to access Firebase from a server using PHP, the Google Auth library, and a wrapper for Firebase's REST...This works great to accomplish that:
use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;
$email = 'account#email.com';
$key = 'private_key_goes_here';
$scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database',
];
$creds = [
'client_email' => $email,
'private_key' => $key,
];
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$token = $serviceAccount->fetchAuthToken($handler);
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
# $value now stores "world"
However, this requires the security rules in Firebase to be universal read / write, which I do not want. If I update my security rules to this:
{
"rules": {
"test": {
".read": "auth != null"
}
}
}
The result in $value becomes {"error": "Permission denied"}. I've searched extensively, and tried numerous permutations and possible solutions, with no conclusive results.
I've used this code to provide JWT tokens to end clients, which can successfully use them and leverage the security rules with no problem. I initially tried that same approach for the server, but was unsuccessful. I opted to try to combine the two methods:
# Snipping code that didn't change...
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$payload = [
'iss' => $email,
'sub' => $email,
'aud' => 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
'iat' => time(),
'exp' => time() + 60 * 60,
'uid' => '123',
'claims' => [
'uid' => '123',
],
];
$payload = $serviceAccount->updateMetadata($payload);
$token = JWT::encode($payload, $key, 'RS256');
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
This seems to get close, but $value now contains {"error": "Missing claim 'kid' in auth header."}. To resolve this, I modified the encode call:
$token = JWT::encode($payload, $key, 'RS256', 'key_id_goes_here');
Which results in a slightly different error: Invalid claim 'kid' in auth header., suggesting I'm on the right track...But not quite there. Using the JWT token directly yields the exact same results. Any ideas what I'm doing wrong? The email, private key, and key id all came directly from the json credential file provided when I created the service account.
I've looked at dozens of pages of documentation and posts, here are the ones that were the most helpful:
Using JWT for Server Auth (Firebase Docs)
Using Custom Tokens to make REST requests to FB DB as an admin
Is it still possible to do server side verification of tokens in Firebase 3?
Cross posted to the Firebase Google Group.
You can specify an auth_variable_override query parameter when authenticating with a service account that will become the auth variable in the security rules. It should be a properly escaped JSON object. For example to do {"uid":123} you'd want to add:
?auth_variable_override=%7B%22uid%22%3A%22123%22%7D
to the end of your request URL.
Ultimately, the solution I ended up using was to switch PHP libraries. I initially dismissed this library because it is moving toward PHP7 only support, which I'm not ready to migrate to yet, but the current version (1.1) worked fine:
use Kreait\Firebase\Configuration;
use Kreait\Firebase\Firebase;
$clientId = '1234567890';
$email = 'account#email.com';
$key = 'private_key_goes_here';
$url = 'https://example.firebaseio.com';
$fbConfig = new Configuration();
$fbConfig->setAuthConfigFile([
'type' => 'service_account',
'client_id' => $clientId,
'client_email' => $email,
'private_key' => $key,
]);
$fb = new Firebase($url, $fbConfig);
$value = $fb->get('test/hello');
# $value now stores "world"

Categories