Using Pimcore 11.3
Trying to implement a Slack Login SSO mechanism. Pimcore Admin UI does not accept my token or authorization which I implemented through AbstractAuthenticator
What I did:
- Created a custom bundle and overwritten login.html.twig for “Sign in with Slack” button (OK)
- Created a SlackAuthenticator by extending AbstractAuthenticator and written methods with Slack Oauth2 logic (OK)
- Created a matching user with my Slack user (using e-mail) and tested logging in with Slack (OK, at least at log level, I can see that e-mail matches Pimcore user fine, and onAuthenticationSuccess is called)
**- Could not manage transferring logged in user to Pimcore Admin UI (Full authentication is required to access this resource.)
**
security:
enable_authenticator_manager: true
providers:
pimcore_admin:
id: PimcoreSecurityUserUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
# Pimcore WebDAV HTTP basic // DO NOT CHANGE!
pimcore_webdav:
pattern: ^/asset/webdav
provider: pimcore_admin
http_basic: ~
# Slack OAuth Firewall
slack_oauth:
pattern: ^/slack/callback$
provider: pimcore_admin
stateless: false
custom_authenticator: AppSecuritySlackAuthenticator
# Pimcore Admin Bundle firewall
pimcore_admin: '%pimcore_admin_bundle.firewall_settings%'
access_control:
# Pimcore admin ACl // DO NOT CHANGE!
- { path: ^/admin/settings/display-custom-logo, roles: PUBLIC_ACCESS }
- { path: ^/admin/login/2fa-verify, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS }
- { path: ^/admin/login/2fa-setup, roles: ROLE_PIMCORE_USER }
- { path: ^/admin/login/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS }
- { path: ^/admin/login$, roles: PUBLIC_ACCESS }
- { path: ^/admin/login/(login|lostpassword|deeplink|csrf-token)$, roles: PUBLIC_ACCESS }
- { path: ^/admin, roles: ROLE_PIMCORE_USER }
- { path: ^/asset/webdav, roles: ROLE_PIMCORE_USER }
- { path: ^/slack/callback$, roles: PUBLIC_ACCESS }
- { path: ^/slack/login, roles: PUBLIC_ACCESS }
role_hierarchy:
# Pimcore admin // DO NOT CHANGE!
ROLE_PIMCORE_ADMIN: [ROLE_PIMCORE_USER]
// removed "if" checks in many places for sake of readability
class SlackAuthenticator extends AbstractAuthenticator
{
private $httpClient;
private $urlGenerator;
private $userProvider;
public function __construct(PimcoreHttpClient $httpClient,UrlGeneratorInterface $urlGenerator,UserProviderInterface $userProvider,
) {
$this->httpClient = $httpClient;
$this->urlGenerator = $urlGenerator;
$this->userProvider = $userProvider;
}
public function supports(Request $request): ?bool
{
return ($request->getPathInfo() === '/slack/callback' && $request->isMethod('GET'));
}
public function authenticate(Request $request): Passport
{
$code = $request->query->get('code');
$response = $this->httpClient->post('https://slack.com/api/oauth.v2.access', [
'form_params' => [
'client_id' => $_SERVER['SLACK_CLIENT_ID'],
'client_secret' => $_SERVER['SLACK_CLIENT_SECRET'],
'code' => $code,
'redirect_uri' => $this->urlGenerator->generate('slack_callback', [], UrlGeneratorInterface::ABSOLUTE_URL),
],
]);
$data = json_decode($response->getBody(), true);
$accessToken = $data['authed_user']['access_token'] ?? null;
$user_id = $data['authed_user']['id'] ?? null;
$response = $this->httpClient->get('https://slack.com/api/users.info', [
'headers' => [
'Authorization' => "Bearer {$_SERVER['SLACK_BOT_USER_OAUTH_TOKEN']}",
],
'query' => [
'user' => $user_id,
],
]);
$userData = json_decode($response->getBody(), true);
$email = $userData['user']['profile']['email'] ?? null;
$user = $this->userProvider->loadUserByIdentifier($email);
return new SelfValidatingPassport(new UserBadge($email, function () use ($user) {
return $user;
}));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return new RedirectResponse($this->urlGenerator->generate('pimcore_admin_index'));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return new RedirectResponse($this->urlGenerator->generate('pimcore_admin_login'));
}
}