AuthController.php 4.95 KB
Newer Older
Jacob Priddy's avatar
Jacob Priddy committed
1 2
<?php

3
namespace App\Http\Controllers\Api;
Jacob Priddy's avatar
Jacob Priddy committed
4 5

use Illuminate\Http\Request;
6
use Illuminate\Cookie\CookieJar;
Jacob Priddy's avatar
Jacob Priddy committed
7
use Illuminate\Http\JsonResponse;
8
use Source\Authorization\Authorizer;
9
use Illuminate\Http\RedirectResponse;
10
use Source\Exceptions\AuthenticationException;
Jacob Priddy's avatar
Jacob Priddy committed
11 12 13
use Source\Exceptions\EntityNotFoundException;
use Source\UseCases\Users\Authenticate\APIPresenter;
use Source\UseCases\Users\Authenticate\AuthenticateUseCase;
14
use Source\UseCases\Users\Authenticate\UserCreationException;
Jacob Priddy's avatar
Jacob Priddy committed
15

Jacob Priddy's avatar
Jacob Priddy committed
16 17 18 19 20
/**
 * @group Authentication
 *
 * This set of routes deals with authentication with the application through SAML and application login.
 */
Jacob Priddy's avatar
Jacob Priddy committed
21 22
class AuthController extends ApiController
{
23 24
    protected CookieJar $cookieJar;

25 26 27 28 29 30
    /**
     * @param \Illuminate\Http\Request         $request
     * @param \Source\Authorization\Authorizer $authorizer
     * @param \Illuminate\Cookie\CookieJar     $cookieJar
     */
    public function __construct(Request $request, Authorizer $authorizer, CookieJar $cookieJar)
Jacob Priddy's avatar
Jacob Priddy committed
31
    {
32 33
        parent::__construct($request, $authorizer);

34
        $this->cookieJar = $cookieJar;
Jacob Priddy's avatar
Jacob Priddy committed
35 36
    }

Jacob Priddy's avatar
Jacob Priddy committed
37 38 39 40 41 42 43 44 45 46 47 48
    /**
     * Welcome
     *
     * This endpoint requires no auth and is the welcome page for any API user.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function welcome(): JsonResponse
    {
        return new JsonResponse(['welcome' => 'Welcome to the elock API.']);
    }

Jacob Priddy's avatar
Jacob Priddy committed
49
    /**
Jacob Priddy's avatar
Jacob Priddy committed
50 51 52 53 54 55 56 57 58 59
     * Login request to application
     *
     * This endpoint returns a token that can be used in other endpoints as well as setting a cookie.
     * One does not need to make a request to this if they have a valid token.
     *
     * @bodyParam email string required The email of the login user. Example: sithL0rd@senate.com
     * @bodyParam password string required The password of the user to login as. Example: I am the senate
     *
     * @response 422 {"message":"The given data was invalid.","errors":{"email":["The email field is required."],"password":["The password field is required."]}}
     *
Jacob Priddy's avatar
Jacob Priddy committed
60 61 62 63
     * @param AuthenticateUseCase $authenticateUseCase
     * @return JsonResponse
     * @throws AuthenticationException
     * @throws EntityNotFoundException
Jacob Priddy's avatar
Jacob Priddy committed
64
     * @throws \Illuminate\Validation\ValidationException
Jacob Priddy's avatar
Jacob Priddy committed
65
     */
Jacob Priddy's avatar
Jacob Priddy committed
66 67
    public function login(AuthenticateUseCase $authenticateUseCase): JsonResponse
    {
Jacob Priddy's avatar
Jacob Priddy committed
68 69 70 71 72
        $this->validate($this->request, [
            'email' => 'required|string|email',
            'password' => 'required|string',
        ]);

73 74
        $presenter = new APIPresenter();

75
        $authenticateUseCase->attempt($presenter, $this->request->all());
Jacob Priddy's avatar
Jacob Priddy committed
76

77
        return $this->respondWithData($presenter->getViewModel())->withCookie(
78
            $this->cookieJar->make(
79 80 81 82 83 84 85
                'api_token',
                $presenter->getViewModel()['token']['value'],
                $presenter->getViewModel()['token']['minutes']
            )
        );
    }

86
    /**
Jacob Priddy's avatar
Jacob Priddy committed
87 88 89 90
     * Start a saml login request
     *
     * This route redirects the user to the running SAML authentication instance to start authentication with SAML
     *
91 92 93
     * @param \Source\UseCases\Users\Authenticate\AuthenticateUseCase $authenticateUseCase
     * @return \Illuminate\Http\RedirectResponse
     */
Jacob Priddy's avatar
Jacob Priddy committed
94 95
    public function samlLogin(AuthenticateUseCase $authenticateUseCase): RedirectResponse
    {
96 97 98 99
        return redirect()->to($authenticateUseCase->handToSaml());
    }

    /**
Jacob Priddy's avatar
Jacob Priddy committed
100 101
     * Handle SAML login
     *
102
     * This API is only meant to be used by SAML after a return from a login.
Jacob Priddy's avatar
Jacob Priddy committed
103
     *
104 105 106
     * @param AuthenticateUseCase $authenticateUseCase
     * @return mixed
     * @throws EntityNotFoundException
Jacob Priddy's avatar
Jacob Priddy committed
107
     * @throws \Source\Exceptions\EntityExistsException
108
     * @throws \Source\Exceptions\AuthorizationException
109
     */
Jacob Priddy's avatar
Jacob Priddy committed
110 111
    public function handle(AuthenticateUseCase $authenticateUseCase)
    {
112 113 114 115 116
        $presenter = new APIPresenter();

        try {
            $authenticateUseCase->handleSamlLogin($presenter);
        } catch (UserCreationException $e) {
117
            $this->setStatusCode(400);
118
            return $this->respondWithError(
119
                'Invalid SAML user given. If you believe this is in error, please contact an administrator.'
120 121 122
            );
        }

123 124 125 126 127 128
        return redirect()->intended(url(config('saml.home_page')))->withCookie(
            $this->cookieJar->make(
                'api_token',
                $presenter->getViewModel()['token']['value'],
                $presenter->getViewModel()['token']['minutes']
            )
Jacob Priddy's avatar
Jacob Priddy committed
129
        );
Jacob Priddy's avatar
Jacob Priddy committed
130
    }
131 132

    /**
Jacob Priddy's avatar
Jacob Priddy committed
133 134 135 136
     * Log out
     *
     * This endpoint logs out of saml and expires the associated api/login token and cookie.
     *
137 138 139
     * @param AuthenticateUseCase $authenticateUseCase
     * @return RedirectResponse
     */
Jacob Priddy's avatar
Jacob Priddy committed
140 141
    public function samlLogout(AuthenticateUseCase $authenticateUseCase): RedirectResponse
    {
142
        $this->cookieJar->queue($this->cookieJar->forget('api_token'));
143 144 145 146 147 148 149

        return redirect()->to(
            $authenticateUseCase->samlLogout(
                $this->request->cookie('api_token')
            )
        );
    }
Jacob Priddy's avatar
Jacob Priddy committed
150
}