Fix #80 - Cannot access accounts with proxy header auth

This commit is contained in:
Bubka 2022-05-19 15:50:06 +02:00
parent 9deb821d53
commit abce20419b
6 changed files with 50 additions and 33 deletions

View File

@ -67,7 +67,7 @@ public function register()
} }
else { else {
return response()->json([ return response()->json([
'message' => $exception->getMessage()], $exception->getCode()); 'message' => $exception->getMessage()], 401);
} }
}); });
} }

View File

@ -3,7 +3,6 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Arr;
class Authenticate extends Middleware class Authenticate extends Middleware
{ {
@ -23,13 +22,11 @@ protected function authenticate($request, array $guards)
$guards = [null]; $guards = [null];
} }
else { else {
// We inject the reserve-proxy guard to ensure it will be available for every routes // We replace routes guard by the reverse proxy guard if necessary
// besides their declared guards. This way we ensure priority to declared guards and
// a fallback to the reverse-proxy guard
$proxyGuard = 'reverse-proxy-guard'; $proxyGuard = 'reverse-proxy-guard';
if (config('auth.defaults.guard') === $proxyGuard && !Arr::has($guards, $proxyGuard)) { if (config('auth.defaults.guard') === $proxyGuard) {
$guards[] = $proxyGuard; $guards = [$proxyGuard];
} }
} }

5
resources/js/api.js vendored
View File

@ -40,6 +40,11 @@ Vue.axios.interceptors.response.use(response => response, error => {
routeName = 'login' routeName = 'login'
} }
if ( error.response.status === 407 ) {
router.push({ name: 'genericError', params: { err: error.response, closable: false } })
throw new Vue.axios.Cancel();
}
// api calls are stateless so when user inactivity is detected // api calls are stateless so when user inactivity is detected
// by the backend middleware it cannot logout the user directly // by the backend middleware it cannot logout the user directly
// so it returns a 418 response. // so it returns a 418 response.

View File

@ -48,12 +48,12 @@ const router = new Router({
{ path: '/settings/webauthn', name: 'settings.webauthn', component: SettingsWebAuthn, meta: { requiresAuth: true } }, { path: '/settings/webauthn', name: 'settings.webauthn', component: SettingsWebAuthn, meta: { requiresAuth: true } },
{ path: '/settings/oauth/pat/create', name: 'settings.oauth.generatePAT', component: GeneratePAT, meta: { requiresAuth: true } }, { path: '/settings/oauth/pat/create', name: 'settings.oauth.generatePAT', component: GeneratePAT, meta: { requiresAuth: true } },
{ path: '/login', name: 'login', component: Login }, { path: '/login', name: 'login', component: Login, meta: { disabledWithAuthProxy: true } },
{ path: '/register', name: 'register', component: Register }, { path: '/register', name: 'register', component: Register, meta: { disabledWithAuthProxy: true } },
{ path: '/password/request', name: 'password.request', component: PasswordRequest }, { path: '/password/request', name: 'password.request', component: PasswordRequest, meta: { disabledWithAuthProxy: true } },
{ path: '/password/reset/:token', name: 'password.reset', component: PasswordReset }, { path: '/password/reset/:token', name: 'password.reset', component: PasswordReset, meta: { disabledWithAuthProxy: true } },
{ path: '/webauthn/lost', name: 'webauthn.lost', component: WebauthnLost }, { path: '/webauthn/lost', name: 'webauthn.lost', component: WebauthnLost, meta: { disabledWithAuthProxy: true } },
{ path: '/webauthn/recover', name: 'webauthn.recover', component: WebauthnRecover }, { path: '/webauthn/recover', name: 'webauthn.recover', component: WebauthnRecover, meta: { disabledWithAuthProxy: true } },
{ path: '/flooded', name: 'flooded',component: Errors,props: true }, { path: '/flooded', name: 'flooded',component: Errors,props: true },
{ path: '/error', name: 'genericError',component: Errors,props: true }, { path: '/error', name: 'genericError',component: Errors,props: true },
{ path: '/404', name: '404',component: Errors,props: true }, { path: '/404', name: '404',component: Errors,props: true },
@ -63,15 +63,20 @@ const router = new Router({
let isFirstLoad = true; let isFirstLoad = true;
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if( to.name === 'accounts') { if( to.name === 'accounts') {
to.params.isFirstLoad = isFirstLoad ? true : false to.params.isFirstLoad = isFirstLoad ? true : false
isFirstLoad = false; isFirstLoad = false;
} }
next() if (to.matched.some(record => record.meta.disabledWithAuthProxy)) {
if (window.appConfig.proxyAuth) {
next({ name: 'accounts' })
}
else next()
}
else next()
}); });
router.afterEach(to => { router.afterEach(to => {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="error-message"> <div class="error-message">
<modal v-model="ShowModal"> <modal v-model="ShowModal" :closable="this.showcloseButton">
<div class="error-message" v-if="$route.name == '404'"> <div class="error-message" v-if="$route.name == '404'">
<p class="error-404"></p> <p class="error-404"></p>
<p>{{ $t('errors.resource_not_found') }}</p> <p>{{ $t('errors.resource_not_found') }}</p>
@ -17,9 +17,9 @@
<div v-else> <div v-else>
<p class="error-generic"></p> <p class="error-generic"></p>
<p>{{ $t('errors.error_occured') }} </p> <p>{{ $t('errors.error_occured') }} </p>
<p v-if="error" class="has-text-grey-lighter">{{ error.message }}</p> <p v-if="error.message" class="has-text-grey-lighter">{{ error.message }}</p>
<p v-if="error.originalMessage" class="has-text-grey-lighter">{{ error.originalMessage }}</p> <p v-if="error.originalMessage" class="has-text-grey-lighter">{{ error.originalMessage }}</p>
<p><router-link :to="{ name: 'accounts' }" class="is-text">{{ $t('errors.refresh') }}</router-link></p> <p><router-link :to="{ name: 'accounts', params: { toRefresh: true } }" class="is-text">{{ $t('errors.refresh') }}</router-link></p>
<p v-if="debugMode == 'development' && error.debug"> <p v-if="debugMode == 'development' && error.debug">
<br> <br>
{{ error.debug }} {{ error.debug }}
@ -37,6 +37,7 @@
data(){ data(){
return { return {
ShowModal : true, ShowModal : true,
showcloseButton: this.closable,
} }
}, },
@ -47,17 +48,21 @@
}, },
error: function() { error: function() {
if( this.err == null ) { if( this.err === null || this.err === undefined ) {
return false return false
} }
else else
{ {
if(this.err.data) { if (this.err.status === 407) {
console.log(this.err.data) return {
'message' : this.$t('errors.auth_proxy_failed'),
'originalMessage' : this.$t('errors.auth_proxy_failed_legend')
}
}
else if(this.err.data) {
return this.err.data return this.err.data
} }
else else {
{
return { 'message' : this.err } return { 'message' : this.err }
} }
@ -66,7 +71,13 @@
}, },
props: ['err'], // on object (error.response) or a string props: {
err: [String, Object], // on object (error.response) or a string
closable: {
type: Boolean,
default: true
}
},
components: { components: {
Modal Modal
@ -81,14 +92,11 @@
}, },
beforeRouteEnter (to, from, next) { beforeRouteEnter (to, from, next) {
// return to home if no err is provided to prevent an empty error message
next(vm => { if (to.params.err == undefined) {
if( !vm.err ) { next({ name: 'accounts' });
next({ name: 'accounts' }); }
} else next()
});
next();
}, },
} }

View File

@ -37,4 +37,6 @@
'security_device_unsupported' => 'Security device unsupported', 'security_device_unsupported' => 'Security device unsupported',
'unsupported_with_reverseproxy' => 'Not applicable when using an auth proxy', 'unsupported_with_reverseproxy' => 'Not applicable when using an auth proxy',
'user_deletion_failed' => 'User account deletion failed, no data have been deleted', 'user_deletion_failed' => 'User account deletion failed, no data have been deleted',
'auth_proxy_failed' => 'Proxy authentication failed',
'auth_proxy_failed_legend' => '2Fauth is configured to run behind an authentication proxy but your proxy does not return the expected header. Check your configuration and try again.'
]; ];