Page MenuHomePhorge

D1435.1775320649.diff
No OneTemporary

Authored By
Unknown
Size
8 KB
Referenced Files
None
Subscribers
None

D1435.1775320649.diff

diff --git a/src/.env.example b/src/.env.example
--- a/src/.env.example
+++ b/src/.env.example
@@ -98,6 +98,7 @@
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
JWT_SECRET=
+JWT_TTL=60
COMPANY_NAME=
COMPANY_ADDRESS=
diff --git a/src/app/Auth/LDAPUserProvider.php b/src/app/Auth/LDAPUserProvider.php
--- a/src/app/Auth/LDAPUserProvider.php
+++ b/src/app/Auth/LDAPUserProvider.php
@@ -26,9 +26,7 @@
}
/**
- * Retrieve the user by its credentials.
- *
- * Please note that this function also validates the password.
+ * Retrieve the user by its credentials (email).
*
* @param array $credentials An array containing the email and password.
*
@@ -36,18 +34,12 @@
*/
public function retrieveByCredentials(array $credentials)
{
- $entries = User::where('email', '=', $credentials['email']);
+ $entries = User::where('email', '=', $credentials['email'])->get();
$count = $entries->count();
if ($count == 1) {
- $user = $entries->select(['id', 'email', 'password', 'password_ldap'])->first();
-
- if (!$this->validateCredentials($user, $credentials)) {
- return null;
- }
-
- return $user;
+ return $entries->first();
}
if ($count > 1) {
diff --git a/src/app/Http/Kernel.php b/src/app/Http/Kernel.php
--- a/src/app/Http/Kernel.php
+++ b/src/app/Http/Kernel.php
@@ -30,13 +30,13 @@
*/
protected $middlewareGroups = [
'web' => [
- \App\Http\Middleware\EncryptCookies::class,
- \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
- \Illuminate\Session\Middleware\StartSession::class,
+ // \App\Http\Middleware\EncryptCookies::class,
+ // \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+ // \Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
- \Illuminate\View\Middleware\ShareErrorsFromSession::class,
- \App\Http\Middleware\VerifyCsrfToken::class,
- \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ // \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ // \App\Http\Middleware\VerifyCsrfToken::class,
+ // \Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -50,17 +50,40 @@
return false
},
// Set user state to "logged in"
- loginUser(token, dashboard) {
- store.commit('logoutUser') // destroy old state data
- store.commit('loginUser')
- localStorage.setItem('token', token)
- axios.defaults.headers.common.Authorization = 'Bearer ' + token
+ loginUser(response, dashboard, update) {
+ if (!update) {
+ store.commit('logoutUser') // destroy old state data
+ store.commit('loginUser')
+ }
+
+ localStorage.setItem('token', response.access_token)
+ axios.defaults.headers.common.Authorization = 'Bearer ' + response.access_token
if (dashboard !== false) {
this.$router.push(store.state.afterLogin || { name: 'dashboard' })
}
store.state.afterLogin = null
+
+ // Refresh the token before it expires
+ let timeout = response.expires_in || 0
+
+ // We'll refresh 60 seconds before the token expires
+ // or immediately when we have no expiration time (on token re-use)
+ if (timeout > 60) {
+ timeout -= 60
+ }
+
+ // TODO: We probably should try a few times in case of an error
+ // TODO: We probably should prevent axios from doing any requests
+ // while the token is being refreshed
+
+ this.refreshTimeout = setTimeout(() => {
+ axios.post('/api/auth/refresh').then(response => {
+ this.loginUser(response.data, false, true)
+ })
+
+ }, timeout * 1000)
},
// Set user state to "not logged in"
logoutUser() {
@@ -68,6 +91,7 @@
localStorage.setItem('token', '')
delete axios.defaults.headers.common.Authorization
this.$router.push({ name: 'login' })
+ clearTimeout(this.refreshTimeout)
},
// Display "loading" overlay inside of the specified element
addLoader(elem) {
diff --git a/src/resources/vue/App.vue b/src/resources/vue/App.vue
--- a/src/resources/vue/App.vue
+++ b/src/resources/vue/App.vue
@@ -21,7 +21,7 @@
.then(response => {
this.isLoading = false
this.$root.stopLoading()
- this.$root.loginUser(token, false)
+ this.$root.loginUser({ access_token: token }, false)
this.$store.state.authInfo = response.data
})
.catch(error => {
diff --git a/src/resources/vue/Login.vue b/src/resources/vue/Login.vue
--- a/src/resources/vue/Login.vue
+++ b/src/resources/vue/Login.vue
@@ -68,7 +68,7 @@
secondfactor: this.secondFactor
}).then(response => {
// login user and redirect to dashboard
- this.$root.loginUser(response.data.access_token)
+ this.$root.loginUser(response.data)
})
}
}
diff --git a/src/resources/vue/PasswordReset.vue b/src/resources/vue/PasswordReset.vue
--- a/src/resources/vue/PasswordReset.vue
+++ b/src/resources/vue/PasswordReset.vue
@@ -129,7 +129,7 @@
password_confirmation: this.password_confirmation
}).then(response => {
// auto-login and goto dashboard
- this.$root.loginUser(response.data.access_token)
+ this.$root.loginUser(response.data)
})
},
// Moves the user a step back in registration form
diff --git a/src/resources/vue/Signup.vue b/src/resources/vue/Signup.vue
--- a/src/resources/vue/Signup.vue
+++ b/src/resources/vue/Signup.vue
@@ -233,7 +233,7 @@
voucher: this.voucher
}).then(response => {
// auto-login and goto dashboard
- this.$root.loginUser(response.data.access_token)
+ this.$root.loginUser(response.data)
})
},
// Moves the user a step back in registration form
diff --git a/src/tests/Feature/Controller/AuthTest.php b/src/tests/Feature/Controller/AuthTest.php
--- a/src/tests/Feature/Controller/AuthTest.php
+++ b/src/tests/Feature/Controller/AuthTest.php
@@ -125,9 +125,42 @@
$response->assertStatus(401);
}
+ /**
+ * Test /api/auth/refresh
+ */
public function testRefresh(): void
{
- // TODO
- $this->markTestIncomplete();
+ // Request with no token, testing that it requires auth
+ $response = $this->post("api/auth/refresh");
+ $response->assertStatus(401);
+
+ // Test the same using JSON mode
+ $response = $this->json('POST', "api/auth/refresh", []);
+ $response->assertStatus(401);
+
+ // Login the user to get a valid token
+ $post = ['email' => 'john@kolab.org', 'password' => 'simple123'];
+ $response = $this->post("api/auth/login", $post);
+ $response->assertStatus(200);
+ $json = $response->json();
+ $token = $json['access_token'];
+
+ // Request with a valid token
+ $response = $this->withHeaders(['Authorization' => 'Bearer ' . $token])->post("api/auth/refresh");
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $this->assertTrue(!empty($json['access_token']));
+ $this->assertTrue($json['access_token'] != $token);
+ $this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']);
+ $this->assertEquals('bearer', $json['token_type']);
+ $new_token = $json['access_token'];
+
+ // TODO: Shall we invalidate the old token?
+
+ // And if the new token is working
+ $response = $this->withHeaders(['Authorization' => 'Bearer ' . $new_token])->get("api/auth/info");
+ $response->assertStatus(200);
}
}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 4:37 PM (3 d, 15 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18821453
Default Alt Text
D1435.1775320649.diff (8 KB)

Event Timeline