Laravel - Two Factor Auth

Laravel - Two Factor Auth
ST
  • Rejestracja:około 5 lat
  • Ostatnio:około rok
  • Postów:45
0

Cześć, potrzebuję porady, nakierowania, potrzebuję zintegrować logowanie konto z Google Authenticator(30 sekundowe kody), mam zrobione aktywowanie, wyłączanie, powiązane z moją aplikacją, jednak nie wiem gdzie mogę zrobić weryfikacje w logowaniu do strony, używam modułu auth laravela, myślałem by w LoginController nadpisać któreś z tych funkcji, ale muszę zrobić sprawdzanie PRZED zalogowaniem a nie PO, jakieś pomysły?

sprawdzam tym kodem:

Kopiuj
$g = new \Google\Authenticator\GoogleAuthenticator();
$salt = '7WAO342QFANY6IKBF7L7SWEUU79WL3VMT920VB5NQMW';
$secret = $username.$salt;
$check_this_code = $_POST['code'];
if ($g->checkCode($secret, $check_this_code)) {
  echo 'Success!';
} else {
  echo 'Invalid login';
}
Kopiuj
<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

trait AuthenticatesUsers
{
    use RedirectsUsers, ThrottlesLogins;

    /**
     * Show the application's login form.
     *
     * @return \Illuminate\View\View
     */
    public function showLoginForm()
    {
        return view('auth.login');
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (method_exists($this, 'hasTooManyLoginAttempts') &&
            $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function validateLogin(Request $request)
    {
        $request->validate([
            $this->username() => 'required|string',
            'password' => 'required|string',
        ]);
    }

    /**
     * Attempt to log the user into the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function attemptLogin(Request $request)
    {
        return $this->guard()->attempt(
            $this->credentials($request), $request->filled('remember')
        );
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        return $request->only($this->username(), 'password');
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    protected function sendLoginResponse(Request $request)
    {
        $request->session()->regenerate();

        $this->clearLoginAttempts($request);

        if ($response = $this->authenticated($request, $this->guard()->user())) {
            return $response;
        }

        return $request->wantsJson()
                    ? new JsonResponse([], 204)
                    : redirect()->intended($this->redirectPath());
    }

    /**
     * The user has been authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        //
    }

    /**
     * Get the failed login response instance.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function sendFailedLoginResponse(Request $request)
    {
        throw ValidationException::withMessages([
            $this->username() => [trans('auth.failed')],
        ]);
    }

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function username()
    {
        return 'email';
    }

    /**
     * Log the user out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    public function logout(Request $request)
    {
        $this->guard()->logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        if ($response = $this->loggedOut($request)) {
            return $response;
        }

        return $request->wantsJson()
            ? new JsonResponse([], 204)
            : redirect('/');
    }

    /**
     * The user has logged out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    protected function loggedOut(Request $request)
    {
        //
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return \Illuminate\Contracts\Auth\StatefulGuard
     */
    protected function guard()
    {
        return Auth::guard();
    }
}

ST
  • Rejestracja:około 5 lat
  • Ostatnio:około rok
  • Postów:45
0

Generalnie, podczas logowania jest dostępny input "token", jeśli konto w bazie ma ustawione "secret" na inne niż NULL, musi wymagać poprawnego "token" podczas logowania, sprawdzając go kodem ktory dałem wyżej.

Kopiuj
$g = new \Google\Authenticator\GoogleAuthenticator();

$secret = $SECRET_Z_BAZY_TABELI_KONTA;
$token = $DANE_Z_INPUT_PRZY_LOGOWANIU;
if ($g->checkCode($secret, $token)) {
  // zaloguj
} else {
  // wyświetl bląd
}
edytowany 3x, ostatnio: storm.
ST
  • Rejestracja:około 5 lat
  • Ostatnio:około rok
  • Postów:45
0

Zrobiłem coś takiego, jednak nie sądzę by było to dobre rozwiązanie, czy ktoś może pomóc jak to zrobić poprawnie?

Kopiuj
public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (method_exists($this, 'hasTooManyLoginAttempts') &&
            $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        $user = \App\Models\User::where(function ($query) use ($request) {
           $query->where($this->username(), '=', $request->get("email"));
           $query->where('password', '=', Hash::make($request->get("password")));
        })->first();

        if ($user && $user->is2FAEnabled()) {
            if (!$request->filled('secret')) {
                return $this->sendFailedLoginResponse($request);
            }

            $qa = new \Google\Authenticator\GoogleAuthenticator();
            if (!$qa->checkCode($user->getSecret(), $request->get("secret"))) {
                return $this->sendFailedLoginResponse($request);
            }
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);

    }
masterc
  • Rejestracja:około 4 lata
  • Ostatnio:około 3 lata
  • Postów:425
0

2FA robisz dopiero po zalogowaniu, najpierw logujesz sie, potem normalnie przechodzisz do routa np index z kontrolera HomeController prawda ?
Wiec wszystkie route maszz w grupie

Kopiuj
Route::group(['middleware' => ['verified'], function () {

Dlatego robisz sobie kolejny swoj middleware np 2fa i dajesz

Kopiuj
Route::group(['middleware' => ['verified', '2fa'], function () {

w nim juz sprawdzasz czy user zalogowany ma wlaczone 2fa czy nie, jesli ma to kierujesz go na kontroler obslugujacy 2fa jego dajesz do grupy route z samym verified juz bez 2fa zeby mial dostep i tam wykonujesz wszystkie czynnosci ze sprawdzeniem kodu itd.

p.s. nigdy nie dotykaj i nie grzeb w gotowych modulach od laravela, wszystko co chcesz zrobic rob jako trait albo mid albo nadpisuj funkcje w oddzielnych plikach


Wymyśliłem, że nie chce mi się.
edytowany 2x, ostatnio: masterc
ST
  • Rejestracja:około 5 lat
  • Ostatnio:około rok
  • Postów:45
0

Ta funkcja którą napisałem jest skopiowana z gotowego modułu i wrzucona w LoginController. Czyli proponujesz zrobić middleware, i w nim sprawdzać czy użytkownik ma włączone 2fa i wtedy weryfikować, następnie np. w ciasteczkach zapisać że został sprawdzony i przepuszczać go do następnych requestów?

masterc
  • Rejestracja:około 4 lata
  • Ostatnio:około 3 lata
  • Postów:425
0

masz gotowe rozwiazanie zainstaluj podaj klucze od googla i dowiedzeni
https://github.com/antonioribeiro/google2fa-laravel


Wymyśliłem, że nie chce mi się.
ST
  • Rejestracja:około 5 lat
  • Ostatnio:około rok
  • Postów:45
1

wolałbym to zrobić samemu, po prostu potrzebuję informacji jak to zrobić, myślę, że pomysł z middleware jest bardzo fajny, dzięki

masterc
  • Rejestracja:około 4 lata
  • Ostatnio:około 3 lata
  • Postów:425
1

Pomysl z middleware jest najlepszy i jedyny sluszny. ale jesl chcesz to zrobic samemu to takie kroki zrob:

  1. zaloguj usera
  2. dodaj do tabeli users kolumne is_2fa domyslnie na 0
  3. zrob mid gdzie sprawdzasz czy Auth()->user()->is_2fa = 0 wtedy zwracasz tylko return $next($request); czy ma 1 i wtedy return redirect()->route('2fa.index'); kierujesz go na kontroler obslugujacy 2fa
  4. oczywiscie route 2fa musi byc w middleware verified ale bez 2fa bo inaczej sie zapetli
  5. w kontrolerze sprawdzasz kod z tego tam google auth i jak sie uda to do sesji dopisujesz verfied_2fa. sesja zginie po wylogowaniu wiec zawsze po ponownym zalofgowaniu user bedzie musial wpsiac kod
  6. robisz modyfikacje w middleware 2fa czyli teraz zapytaujesz czy sesja verfied_2fa nie istnieje i Auth()->user()->is_2fa = 1
  • jesli sesja nie istnieje a wymaga 2fa to przekieruje na wpisanie kodu,
  • jesli sesja istnieje to warunek nie jest spelniony wiec przekiruje go do systemu
  • jesli sesja nie istnieje i nie ma wymaganego 2fa to rowniez przkieruje go do systemu

Jakos tak chyba.

p.s. Dodalbym jeszcze przy wlaczaniu 2FA tablice 10 wygenerowanych losowych słów(znakow po 8 na kazde slowo) zeby user sobie to zapisal i jak wejdzie i sie zaloguje a ty przekeirujesz go na 2fa. i on zgubi teefon nie zrobi kopii itd to guzik uzyskaj dostep z kopii zapasowej i pokazesz mu 10 inputow i jak wpisze te slowa to zdejmujesz mu blokade 2fa i moze od nowa ja sobie wlaczyc


Wymyśliłem, że nie chce mi się.
edytowany 2x, ostatnio: masterc
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)