PHP code example of sandermuller / socialite-solana
1. Go to this page and download the library: Download sandermuller/socialite-solana library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
sandermuller / socialite-solana example snippets
use Illuminate\Support\Facades\Event;
use SanderMuller\SocialiteSolana\SocialiteSolanaExtendSocialite;
use SocialiteProviders\Manager\SocialiteWasCalled;
public function boot(): void
{
Event::listen(
SocialiteWasCalled::class,
[SocialiteSolanaExtendSocialite::class, 'handle'],
);
}
'solana' => [
// Required by socialiteproviders/manager but unused by this driver.
'client_id' => env('SOLANA_CLIENT_ID', 'unused'),
'client_secret' => env('SOLANA_CLIENT_SECRET', 'unused'),
'redirect' => env('SOLANA_REDIRECT_URI', '/auth/solana/callback'),
// Domain shown in the SIWS message. Defaults to APP_URL host.
'domain' => env('SOLANA_SIWS_DOMAIN'),
// Canonical URI of the resource being signed in to. Defaults to APP_URL.
'uri' => env('SOLANA_SIWS_URI'),
// Human-readable statement (optional).
'statement' => env('SOLANA_SIWS_STATEMENT', 'Sign in to authenticate.'),
// Solana cluster: mainnet | devnet | testnet | localnet.
'chain' => env('SOLANA_SIWS_CHAIN', 'mainnet'),
// Challenge lifetime in seconds (minimum 60). Default 180 matches typical
// SIWS reference implementations.
'ttl' => (int) env('SOLANA_SIWS_TTL', 180),
// Optional CAIP-122 resource URIs (list of strings).
'resources' => [],
// Where the issued challenge lives between buildChallengeFor() and
// verifyCredentials(). Values: 'session' (default), 'cache', or an FQCN
// implementing SanderMuller\SocialiteSolana\Contracts\ChallengeStore.
'store' => env('SOLANA_CHALLENGE_STORE', 'session'),
],
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;
use SanderMuller\SocialiteSolana\Exceptions\SolanaAuthException;
Route::post('/auth/solana/challenge', function () {
return Socialite::driver('solana')->challenge();
})->middleware('web');
Route::post('/auth/solana/callback', function () {
try {
$solanaUser = Socialite::driver('solana')->user();
} catch (SolanaAuthException $e) {
return response()->json(['error' => $e->getMessage()], 422);
}
$user = \App\Models\User::firstOrCreate(
['solana_public_key' => $solanaUser->getId()],
['password' => Hash::make(Str::random(32))],
);
Auth::login($user, remember: true);
return response()->json(['redirect' => '/home']);
})->middleware('web');
use Laravel\Socialite\Facades\Socialite;
use Livewire\Component;
use SanderMuller\SocialiteSolana\Exceptions\SolanaAuthException;
class SolanaLogin extends Component
{
public string $walletAddress = '';
/**
* Issue a SIWS challenge. The JS layer should `$wire.set('walletAddress', pubkey)`
* before calling this so the component already knows the address when verify() fires.
*/
public function requestSignInChallenge(string $publicKey): array
{
return Socialite::driver('solana')->buildChallengeFor($publicKey);
}
public function signIn(string $signature, string $message, string $nonce): void
{
try {
$solanaUser = Socialite::driver('solana')->verifyCredentials(
$this->walletAddress, $signature, $message, $nonce,
);
} catch (SolanaAuthException $e) {
$this->addError('solana', $e->getMessage());
return;
}
// ... resolve user, log in, redirect
}
}
use SanderMuller\SocialiteSolana\Exceptions\AddressMismatchException;
use SanderMuller\SocialiteSolana\Exceptions\ChallengeExpiredException;
use SanderMuller\SocialiteSolana\Exceptions\ChallengeNotFoundException;
use SanderMuller\SocialiteSolana\Exceptions\InvalidPublicKeyException;
use SanderMuller\SocialiteSolana\Exceptions\InvalidSignatureException;
use SanderMuller\SocialiteSolana\Exceptions\MalformedSignatureException;
use SanderMuller\SocialiteSolana\Exceptions\MessageMismatchException;
use SanderMuller\SocialiteSolana\Exceptions\MissingChallengeParameterException;
try {
$solanaUser = Socialite::driver('solana')->user();
} catch (MissingChallengeParameterException) {
return back()->withErrors(['wallet' => 'Wallet response was incomplete. Try again.']);
} catch (ChallengeExpiredException | ChallengeNotFoundException) {
return back()->withErrors(['wallet' => 'Sign-in window expired. Click sign in to retry.']);
} catch (InvalidPublicKeyException) {
return back()->withErrors(['wallet' => 'That wallet address is not a valid Solana public key.']);
} catch (MessageMismatchException | AddressMismatchException) {
abort(400, 'Tampered request.'); // Wallet signed something the server did not issue — usually a bug, occasionally an attack.
} catch (MalformedSignatureException) {
// Wallet returned a signature that's not 64 raw bytes — extension bug or wrong wallet. Catch BEFORE InvalidSignatureException.
return back()->withErrors(['wallet' => 'Your wallet did not return a valid signature. Try a different wallet or reconnect.']);
} catch (InvalidSignatureException) {
return back()->withErrors(['wallet' => 'Signature did not match. The user may have switched wallets mid-flow. Please try again.']);
}
use SanderMuller\SocialiteSolana\Contracts\ChallengeStore;
$this->app->singleton(ChallengeStore::class, MyRedisStore::class);
interface ChallengeStore
{
public function put(Challenge $challenge): void;
public function find(string $nonce): ?Challenge;
public function forget(string $nonce): void;
}
use Illuminate\Support\Facades\Log;
use Laravel\Socialite\Facades\Socialite;
use SanderMuller\SocialiteSolana\Provider;
private function solanaProvider(): Provider
{
/** @var Provider $provider */
$provider = Socialite::driver('solana');
$provider->setLogger(Log::channel('security'));
return $provider;
}
// Use it like:
$user = $this->solanaProvider()->user();
// Avoid unless you actually want the routing to be app-wide:
$this->app->bind(\Psr\Log\LoggerInterface::class, fn () => Log::channel('security'));
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.