-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
badde48
commit 9ed0f97
Showing
36 changed files
with
2,772 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) Elton Pastilha, Vladyslav Adamovych, João Ricardo | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is furnished | ||
to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
{ | ||
"name": "destruidorpt/laravel-sqrl-auth", | ||
"description": "Package for Authentication between Laravel and SQRL", | ||
"keywords": ["SQRL", "laravel", "authentication", "QRCode", "auth", "login", "package", "Must have", "MCIF", "IPLeiria", "ESTG"], | ||
"license": "MIT", | ||
"minimum-stability": "dev", | ||
"prefer-stable": true, | ||
"authors": [ | ||
{ | ||
"name": "Elton Pastilha", | ||
"email": "elton_ola@hotmail.com", | ||
"homepage": "https://github.com/DestruidorPT", | ||
"role": "Developer, CyberSecurity Expert and Gamer" | ||
}, | ||
{ | ||
"name": "Vladyslav Adamovych", | ||
"email": "vladyslav.adamovych@ipleiria.pt", | ||
"homepage": "https://github.com/nekkiii", | ||
"role": "Developer, CyberSecurity Expert and Gamer" | ||
}, | ||
{ | ||
"name": "João Ricardo", | ||
"email": "joao_pricardo@hotmail.com", | ||
"homepage": "https://github.com/kratezo", | ||
"role": "Developer, CyberSecurity Expert and Gamer" | ||
} | ||
], | ||
"require": { | ||
"php": ">=7.2", | ||
"laravel/framework": ">=6.0", | ||
"simplesoftwareio/simple-qrcode": ">=2.0" | ||
}, | ||
"require-dev": {}, | ||
"autoload": { | ||
"psr-4": { | ||
"DestruidorPT\\LaravelSQRLAuth\\": "/src" | ||
}, | ||
"classmap": [ | ||
"src" | ||
] | ||
}, | ||
"extra": { | ||
"laravel": { | ||
"providers": [ | ||
"DestruidorPT\\LaravelSQRLAuth\\LaravelSQRLAuthServiceProvider" | ||
] | ||
} | ||
} | ||
} |
237 changes: 237 additions & 0 deletions
237
exemple/app/Http/Controllers/LaravelSQRLAuthExemples/ExempleController.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
<?php | ||
|
||
namespace App\Http\Controllers\LaravelSQRLAuthExemples; | ||
|
||
|
||
use Illuminate\Http\Request; | ||
use App\Http\Controllers\Controller; | ||
use Illuminate\Support\Facades\Auth; | ||
use Illuminate\Support\Facades\Hash; | ||
use App\User; | ||
use DestruidorPT\LaravelSQRLAuth\App\Sqrl_pubkey; | ||
use DestruidorPT\LaravelSQRLAuth\App\Http\Controllers\SQRL\SQRLController; | ||
|
||
class ExempleController extends Controller | ||
{ | ||
/** | ||
* Function to get the login page and check if given by paramer GET["nut"] is passed | ||
* if $_GET["nut"] exist will check if the nonce is valid and return object type Sqrl_pubkey if the | ||
* no SQRL Client registed is not associated to any user, if returns a number means is ID of the user | ||
* associated and then proceds to authenticate that user | ||
* | ||
* @GET string nut | ||
* | ||
* @return View | ||
*/ | ||
public function getAuthPage() | ||
{ | ||
if(isset($_GET["nut"]) && !empty($_GET["nut"])) { // Check if the nut exist or if it's past on URL https://site.test?nut=<nonce value> | ||
$object = SQRLController::getUserByOriginalNonceIfCanBeAuthenticated($_GET["nut"]); //Get the user by the original nonce | ||
if(isset($object)) { //Will be null if the nonce expired or is invalid | ||
if($object instanceof Sqrl_pubkey) { // This only happen when no SQRL Client is associated to the user, then Sqrl_pubkey from SQRL CLient is returned | ||
//new user | ||
return view('LaravelSQRLAuthExemples.newsqrl');//View for the user to create account or associate to one already created | ||
} else if($object > 0) { //This happen when SQRL Client is associated to a user, so the value is number and is the id of the user | ||
Auth::loginUsingId($object); //This is for authenticate the user with that id | ||
} | ||
} | ||
} | ||
if (Auth::check()) { | ||
// The user is logged in... | ||
return redirect()->intended('dashboard'); | ||
} | ||
return view('LaravelSQRLAuthExemples.login', SQRLController::getNewAuthNonce()); | ||
} | ||
|
||
/** | ||
* Function to post credentials from login page and check if user exist and are valid credentials, | ||
* But will check first if the user can login by normal login given by paramer GET["nut"] is passed | ||
* if $_GET["nut"] exist will check if the nonce is valid and return object type Sqrl_pubkey if the | ||
* no SQRL Client registed is not associated to any user, if returns a number means is ID of the user | ||
* associated and then proceds to authenticate that user | ||
* | ||
* @GET string nut | ||
* | ||
* @return View | ||
*/ | ||
public function login(Request $request) | ||
{ | ||
if (Auth::check()) { | ||
// The user is logged in... | ||
return redirect()->intended('dashboard'); | ||
} | ||
$validatedData = $request->validate([ | ||
'email' => 'required|email|exists:users,email', | ||
'password' => 'required|string', | ||
]); | ||
$user = User::where("email", "=", $validatedData["email"])->first(); | ||
if(isset($user)){ //Check if the user exists | ||
if(!SQRLController::checkIfUserCanAuthByNormalLogin($user->id)) { //Check if the user can not be authentication by normal login authentication | ||
return redirect()->intended('login')->withErrors(['SQRL Only Allowed!!!']);//If returned false then the user only can authenticate by SQRL | ||
} | ||
} | ||
$credentials = $request->only('email', 'password'); | ||
if (Auth::attempt($credentials)) { | ||
// Authentication passed... | ||
return redirect()->intended('dashboard'); | ||
} | ||
return redirect()->intended('login')->withErrors(['Login Fail!!!']); | ||
} | ||
|
||
/** | ||
* Function to post the new user information and can associate the new user | ||
* to the SQRL Client Public Key that was not previously associated to any user | ||
* | ||
* @GET string nut | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function newAcc(Request $request) | ||
{ | ||
$validatedData = $request->validate([ | ||
'name' => 'required|string', | ||
'email' => 'required|unique:users,email', | ||
'password' => 'required|string', | ||
]); | ||
$validatedData['password'] = Hash::make($validatedData['password']); | ||
|
||
|
||
$user = new User($validatedData); | ||
$user->save(); | ||
//dd($user); | ||
if(isset($user)) { // Check if user is not null | ||
if(isset($_GET["nut"]) && !empty($_GET["nut"])) { // Check if the nut exist or if it's past on URL https://site.test?nut=<nonce value> | ||
$object = SQRLController::getUserByOriginalNonceIfCanBeAuthenticated($_GET["nut"]); //Get the user by the original nonce | ||
if(isset($object)) { //Will be null if the nonce expired or is invalid | ||
if($object instanceof Sqrl_pubkey) { // This only happen when no SQRL Client is associated to the user, then Sqrl_pubkey from SQRL CLient is returned | ||
//new user | ||
$object->user_id = $user->id; // So the user was created then lets associate to the new user | ||
$object->save(); | ||
} | ||
} | ||
} | ||
Auth::loginUsingId($user->id); | ||
} | ||
if (Auth::check()) { | ||
// Authentication passed... | ||
return redirect()->intended('dashboard'); | ||
} | ||
return redirect()->intended('login'); | ||
} | ||
|
||
/** | ||
* Function to post the new credentials of the user login and for associate the user | ||
* to the SQRL Client Public Key that was not previously associated to any user | ||
* | ||
* @GET string nut | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function newlogin(Request $request) | ||
{ | ||
$credentials = $request->only('email', 'password'); | ||
if (Auth::attempt($credentials)) { // Do a login of the user | ||
// Authentication passed... | ||
$object = SQRLController::getUserByOriginalNonceIfCanBeAuthenticated($_GET["nut"]); //Get the user by the original nonce | ||
if(isset($object)) { //Will be null if the nonce expired or is invalid | ||
if($object instanceof Sqrl_pubkey) { // This only happen when no SQRL Client is associated to the user, then Sqrl_pubkey from SQRL CLient is returned | ||
//new user | ||
$object->user_id = Auth::id(); // So the user was created then lets associate to the user already existing | ||
$object->save(); | ||
} | ||
} | ||
return redirect()->intended('dashboard'); | ||
} | ||
return redirect()->intended('login'); | ||
} | ||
|
||
/** | ||
* Function to logout user | ||
* | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function logout(Request $request) | ||
{ | ||
Auth::logout(); | ||
return redirect()->intended('login'); | ||
} | ||
|
||
/** | ||
* Function to get the dashboard page | ||
* | ||
* | ||
* @return View | ||
*/ | ||
public function getDashboardPage() | ||
{ | ||
if (Auth::check()) { | ||
// The user is logged in... | ||
return view('LaravelSQRLAuthExemples.dashboard', ["user_name" => Auth::user()->name]); | ||
} | ||
return redirect()->intended('login'); | ||
} | ||
|
||
/** | ||
* Function to post the new question to the user by SQRL application, in this exemple is a question if the user confer a transaction of money | ||
* | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function getTransferConfirmation(Request $request) | ||
{ | ||
$validatedData = $request->validate([ | ||
'money' => 'required|numeric|min:1', | ||
'btn1' => 'nullable|string|required_with:url1', | ||
'url1' => 'nullable|string', | ||
'btn2' => 'nullable|string|required_with:url2', | ||
'url2' => 'nullable|string', | ||
]); | ||
$data = SQRLController::getNewQuestionNonce(env('SQRL_URL_LOGIN', 'https://sqrl.test/login'), env('SQRL_URL_LOGIN', 'https://sqrl.test/login'), "Do you confirm ".$validatedData["money"]."$ tranfering?", $validatedData["btn1"], $validatedData["url1"], $validatedData["btn2"], $validatedData["url2"]); | ||
$data["money"] = $validatedData["money"]; | ||
return view('LaravelSQRLAuthExemples.transfer', $data); | ||
} | ||
|
||
/** | ||
* Function to get the page to reset password | ||
* | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function getResetPWPage() | ||
{ | ||
return view('LaravelSQRLAuthExemples.forgotpassword'); | ||
} | ||
|
||
/** | ||
* Function to post the information of user to reset the password, | ||
* but only will reset the password if user account allowed | ||
* | ||
* @param Request $request | ||
* | ||
* @return View | ||
*/ | ||
public function resetPW(Request $request) | ||
{ | ||
$validatedData = $request->validate([ | ||
'email' => 'required|email|exists:users,email', | ||
'password' => 'string', | ||
]); | ||
$user = User::where("email", "=", $validatedData["email"])->first(); | ||
if(isset($user)){ //Check if the user exists | ||
if(!SQRLController::checkIfUserCanUseRecoverPassword($user->id)) { //Check if the user can not recovery the password | ||
return redirect()->intended('resetpw')->withErrors(['SQRL not Allowed recovery account!!!']); //This means that the account as hardlocked by SQRL Client that not Allowed recovery password by email or personal questions | ||
} else if(isset($validatedData["password"]) && !empty($validatedData["password"])) { | ||
$user->password = $validatedData["password"]; | ||
$user->save(); | ||
} | ||
} | ||
return view('LaravelSQRLAuthExemples.newpassword', ['email' => $validatedData["email"]]); | ||
} | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
exemple/resources/views/LaravelSQRLAuthExemples/dashboard.blade.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<!DOCTYPE html> | ||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
|
||
<title>Laravel</title> | ||
|
||
<!-- Fonts --> | ||
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet"> | ||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/css/bootstrap.min.css" integrity="sha384-SI27wrMjH3ZZ89r4o+fGIJtnzkAnFs3E4qz9DIYioCQ5l9Rd/7UAa8DHcaL8jkWt" crossorigin="anonymous"> | ||
<!-- Styles --> | ||
<style> | ||
body { | ||
height: 100vh; | ||
width: 100%; | ||
background: linear-gradient(to bottom, rgba(255,255,255,0.15) 0%, rgba(0,0,0,0.15) 100%), radial-gradient(at top center, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.40) 120%) #989898; | ||
background-blend-mode: multiply,multiply; | ||
} | ||
.container { | ||
height: 90%; | ||
width: 100%; | ||
margin-top: 10vh; | ||
} | ||
.card { | ||
background-image: linear-gradient(120deg, #f6d365 0%, #fda085 100%); | ||
} | ||
.sqrl-logo { | ||
height: 100px !important; | ||
width: 100px !important; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<div class="card mx-auto my-auto" style="max-width: 540px;"> | ||
<div class="row no-gutters"> | ||
<div class="col-sm mx-2 my-3"> | ||
<form method="post" action="/logout"> | ||
{{ csrf_field() }} | ||
<button type="submit" class="btn btn-link text-dark" style="float: right;">Logout</button> | ||
</form> | ||
<div class="card-body"> | ||
<h5 class="card-title">Auth User: {{$user_name ?? ''}}</h5> | ||
<form method="post" action="/transfer"> | ||
{{ csrf_field() }} | ||
<div class="form-group"> | ||
<label for="money">Money To Transfer:</label> | ||
<input name="money" type="number" step="0.01" class="form-control" id="money"> | ||
</div> | ||
<div class="form-group"> | ||
<label for="btn1">Button_1</label> | ||
<input name="btn1" type="text" class="form-control" id="btn1"> | ||
</div> | ||
<div class="form-group"> | ||
<label for="url1">URL_1</label> | ||
<input name="url1" type="text" class="form-control" id="url1"> | ||
</div> | ||
<div class="form-group"> | ||
<label for="btn2">Button_2</label> | ||
<input name="btn2" type="text" class="form-control" id="btn2"> | ||
</div> | ||
<div class="form-group"> | ||
<label for="url2">URL_2</label> | ||
<input name="url2" type="text" class="form-control" id="url2"> | ||
</div> | ||
<button type="submit" class="btn btn-dark">Transfer</button> | ||
</form> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</body> | ||
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> | ||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/js/bootstrap.min.js" integrity="sha384-3qaqj0lc6sV/qpzrc1N5DC6i1VRn/HyX4qdPaiEFbn54VjQBEU341pvjz7Dv3n6P" crossorigin="anonymous"></script> | ||
</html> |
Oops, something went wrong.