Skip to content
Merged

OAuth2 #5753

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
SSO: Display: External logins under below the login form - refs BT#21881
  • Loading branch information
AngelFQC committed Aug 28, 2024
commit 23e182a5cbdb80352adfa348898023e89ae0a45b
2 changes: 1 addition & 1 deletion assets/css/scss/atoms/_divider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

&[aria-orientation="horizontal"] {
@apply before:absolute before:block before:left-0 before:w-full before:top-1/2 before:content-[""] before:border-t before:border-solid before:border-gray-25
flex w-full relative items-center my-4 px-2;
flex relative items-center my-4 px-2;

div {
@apply first:px-2;
Expand Down
1 change: 1 addition & 0 deletions assets/css/scss/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
@import "organisms/course_card";
@import "organisms/datatable";
@import "organisms/dataview";
@import "organisms/external_logins";
@import "organisms/modals";
@import "organisms/menu";
@import "organisms/sidebar";
Expand Down
15 changes: 15 additions & 0 deletions assets/css/scss/organisms/_external_logins.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.external-logins {
@apply flex flex-col gap-2 items-center;

&__divider {
@apply w-60 mx-auto uppercase;
}

&__button-list {
@apply space-y-4;
}

&__button {
@apply border border-gray-25 bg-white rounded-lg text-gray-90 py-4 px-12 block font-semibold;
}
}
3 changes: 3 additions & 0 deletions assets/vue/components/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
/>
</div>
</form>

<ExternalLoginButtons />
</div>
</template>

Expand All @@ -77,6 +79,7 @@ import Password from "primevue/password"
import InputSwitch from "primevue/inputswitch"
import { useI18n } from "vue-i18n"
import { useLogin } from "../composables/auth/login"
import ExternalLoginButtons from "./login/LoginExternalButtons.vue"

const { t } = useI18n()

Expand Down
37 changes: 37 additions & 0 deletions assets/vue/components/login/LoginExternalButtons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup>
import BaseAppLink from "../basecomponents/BaseAppLink.vue"
import BaseDivider from "../basecomponents/BaseDivider.vue"
import { useI18n } from "vue-i18n"
import { usePlatformConfig } from "../../store/platformConfig"

const { t } = useI18n()

const platformConfig = usePlatformConfig()
</script>

<template>
<div
v-if="platformConfig.externalAuthentication.length > 0"
class="external-logins"
>
<BaseDivider
:title="t('Or')"
align="center"
class="external-logins__divider"
/>

<ul class="external-logins__button-list">
<li
v-for="(extAuth, idx) in platformConfig.externalAuthentication"
:key="idx"
>
<BaseAppLink
:url="extAuth.url"
class="external-logins__button"
>
{{ t("Continue with %s", [extAuth.title]) }}
</BaseAppLink>
</li>
</ul>
</div>
</template>
4 changes: 4 additions & 0 deletions assets/vue/store/platformConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const usePlatformConfig = defineStore("platformConfig", () => {
const studentView = ref("teacherview")
const plugins = ref([])
const visualTheme = ref("chamilo")
const externalAuthentication = ref([])

async function findSettingsRequest() {
isLoading.value = true
Expand All @@ -22,6 +23,8 @@ export const usePlatformConfig = defineStore("platformConfig", () => {
studentView.value = data.studentview

plugins.value = data.plugins

externalAuthentication.value = data.external_authentication
} catch (e) {
console.log(e)
} finally {
Expand All @@ -48,5 +51,6 @@ export const usePlatformConfig = defineStore("platformConfig", () => {
getSetting,
isStudentViewActive,
visualTheme,
externalAuthentication,
}
})
3 changes: 3 additions & 0 deletions config/authentication.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ parameters:
default:
generic:
enabled: false
title: 'External'
client_id: ''
client_secret: ''
provider_options:
Expand Down Expand Up @@ -34,13 +35,15 @@ parameters:

facebook:
enabled: false
title: 'Facebook'
client_id: ''
client_secret: ''
graph_api_version: 'v20.0'
redirect_params: { }

keycloak:
enabled: false
title: 'Keycloak'
client_id: ''
client_secret: ''
auth_server_url: ''
Expand Down
3 changes: 3 additions & 0 deletions src/CoreBundle/Controller/PlatformConfigurationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use bbb;
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
use Chamilo\CoreBundle\ServiceHelper\AuthenticationConfigHelper;
use Chamilo\CoreBundle\ServiceHelper\ThemeHelper;
use Chamilo\CoreBundle\ServiceHelper\TicketProjectHelper;
use Chamilo\CoreBundle\ServiceHelper\UserHelper;
Expand All @@ -29,6 +30,7 @@ public function __construct(
private readonly TicketProjectHelper $ticketProjectHelper,
private readonly UserHelper $userHelper,
private readonly ThemeHelper $themeHelper,
private readonly AuthenticationConfigHelper $authenticationConfigHelper,
) {}

#[Route('/list', name: 'platform_config_list', methods: ['GET'])]
Expand All @@ -41,6 +43,7 @@ public function list(SettingsManager $settingsManager): Response
'studentview' => $requestSession->get('studentview'),
'plugins' => [],
'visual_theme' => $this->themeHelper->getVisualTheme(),
'external_authentication' => $this->authenticationConfigHelper->getEnabledProviders(),
];
$variables = [];

Expand Down
56 changes: 43 additions & 13 deletions src/CoreBundle/ServiceHelper/AuthenticationConfigHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,27 @@
use Chamilo\CoreBundle\Entity\AccessUrl;
use InvalidArgumentException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

use function Symfony\Component\String\u;

readonly class AuthenticationConfigHelper
{
public function __construct(
private ParameterBagInterface $parameterBag,
private AccessUrlHelper $urlHelper,
private UrlGeneratorInterface $urlGenerator,
) {}

public function getParams(string $providerName, ?AccessUrl $url = null): array
{
$urlId = $url ? $url->getId() : $this->urlHelper->getCurrent()->getId();

$authentication = $this->parameterBag->get('authentication');

if (isset($authentication[$urlId])) {
$urlParams = $authentication[$urlId];
} elseif (isset($authentication['default'])) {
$urlParams = $authentication['default'];
} else {
throw new InvalidArgumentException('Invalid access URL configuration');
}
$providers = $this->getProvidersForUrl($url);

if (!isset($urlParams[$providerName])) {
if (!isset($providers[$providerName])) {
throw new InvalidArgumentException('Invalid authentication provider for access URL');
}

return $urlParams[$providerName];
return $providers[$providerName];
}

public function isEnabled(string $methodName, ?AccessUrl $url = null): bool
Expand All @@ -44,4 +38,40 @@ public function isEnabled(string $methodName, ?AccessUrl $url = null): bool

return $configParams['enabled'] ?? false;
}

public function getEnabledProviders(?AccessUrl $url = null): array
{
$urlProviders = $this->getProvidersForUrl($url);

$enabledProviders = [];

foreach ($urlProviders as $providerName => $providerParams) {
if ($providerParams['enabled'] ?? false) {
$enabledProviders[] = [
'name' => $providerName,
'title' => $providerParams['title'] ?? u($providerName)->title(),
'url' => $this->urlGenerator->generate("chamilo.oauth2_{$providerName}_start"),
];
}
}

return $enabledProviders;
}

private function getProvidersForUrl(?AccessUrl $url): array
{
$urlId = $url ? $url->getId() : $this->urlHelper->getCurrent()->getId();

$authentication = $this->parameterBag->get('authentication');

if (isset($authentication[$urlId])) {
return $authentication[$urlId];
}

if (isset($authentication['default'])) {
return $authentication['default'];
}

throw new InvalidArgumentException('Invalid access URL configuration');
}
}