33namespace Pterodactyl \Http \Controllers \API ;
44
55use JWTAuth ;
6+ use Hash ;
7+ use Validator ;
8+
69use Tymon \JWTAuth \Exceptions \JWTException ;
710
11+ use Dingo \Api \Exception \StoreResourceFailedException ;
12+ use Symfony \Component \HttpKernel \Exception \UnauthorizedHttpException ;
13+ use Symfony \Component \HttpKernel \Exception \ServiceUnavailableHttpException ;
14+ use Symfony \Component \HttpKernel \Exception \TooManyRequestsHttpException ;
15+
816use Illuminate \Http \Request ;
9- use \ Symfony \ Component \ HttpKernel \ Exception \ UnauthorizedHttpException ;
10- use \ Symfony \ Component \ HttpKernel \ Exception \ ServiceUnavailableHttpException ;
17+ use Illuminate \ Foundation \ Auth \ ThrottlesLogins ;
18+ use Illuminate \ Foundation \ Auth \ AuthenticatesAndRegistersUsers ;
1119
1220use Pterodactyl \Transformers \UserTransformer ;
1321use Pterodactyl \Models ;
1826class AuthController extends BaseController
1927{
2028
29+ use AuthenticatesAndRegistersUsers, ThrottlesLogins;
30+
31+ /**
32+ * Lockout time for failed login requests.
33+ *
34+ * @var integer
35+ */
36+ protected $ lockoutTime = 120 ;
37+
38+ /**
39+ * After how many attempts should logins be throttled and locked.
40+ *
41+ * @var integer
42+ */
43+ protected $ maxLoginAttempts = 3 ;
44+
45+ /**
46+ * Create a new authentication controller instance.
47+ *
48+ * @return void
49+ */
50+ public function __construct ()
51+ {
52+ //
53+ }
54+
2155 /**
2256 * Authenticate
2357 *
@@ -29,16 +63,42 @@ class AuthController extends BaseController
2963 * @Response(200, body={"token": "<jwt-token>"})
3064 */
3165 public function postLogin (Request $ request ) {
32- $ credentials = $ request ->only ('email ' , 'password ' );
66+
67+ $ validator = Validator::make ($ request ->only (['email ' , 'password ' ]), [
68+ 'email ' => 'required|email ' ,
69+ 'password ' => 'required|min:8 '
70+ ]);
71+
72+ if ($ validator ->fails ()) {
73+ throw new StoreResourceFailedException ('Required authentication fields were invalid. ' , $ validator ->errors ());
74+ }
75+
76+ $ throttled = $ this ->isUsingThrottlesLoginsTrait ();
77+ if ($ throttled && $ this ->hasTooManyLoginAttempts ($ request )) {
78+ throw new TooManyRequestsHttpException ('You have been login throttled for 120 seconds. ' );
79+ }
80+
81+ // Is the email & password valid?
82+ $ user = Models \User::where ('email ' , $ request ->input ('email ' ))->first ();
83+ if (!$ user || !Hash::check ($ request ->input ('password ' ), $ user ->password )) {
84+ if ($ throttled ) {
85+ $ this ->incrementLoginAttempts ($ request );
86+ }
87+ throw new UnauthorizedHttpException ('A user by those credentials was not found. ' );
88+ }
89+
90+ // @TODO: validate TOTP if enabled on account?
91+ // Perhaps this could be implemented in such a way that they login to their
92+ // account and generate a one time password that can be used? Would be a pain in
93+ // the butt for multiple API requests though. Maybe just included a 'totp' field
94+ // that can include the token for that timestamp. Would allow for programtic
95+ // generation of the code and API requests.
96+ if ($ user ->root_admin !== 1 ) {
97+ throw new UnauthorizedHttpException ('This account does not have permission to interface this API. ' );
98+ }
3399
34100 try {
35- $ token = JWTAuth::attempt ($ credentials , [
36- 'permissions ' => [
37- 'view_users ' => true ,
38- 'edit_users ' => true ,
39- 'delete_users ' => false ,
40- ]
41- ]);
101+ $ token = JWTAuth::fromUser ($ user );
42102 if (!$ token ) {
43103 throw new UnauthorizedHttpException ('' );
44104 }
0 commit comments