1616use OCA \UserOIDC \Event \ExchangedTokenRequestedEvent ;
1717use OCA \UserOIDC \Listener \ExchangedTokenRequestedListener ;
1818use OCA \UserOIDC \Listener \TimezoneHandlingListener ;
19+ use OCA \UserOIDC \MagentaBearer \MBackend ;
1920use OCA \UserOIDC \Service \ID4MeService ;
21+ use OCA \UserOIDC \Service \ProvisioningEventService ;
22+ use OCA \UserOIDC \Service \ProvisioningService ;
2023use OCA \UserOIDC \Service \SettingsService ;
21- use OCA \UserOIDC \Service \TokenService ;
22- use OCA \UserOIDC \User \Backend ;
2324use OCP \AppFramework \App ;
2425use OCP \AppFramework \Bootstrap \IBootContext ;
2526use OCP \AppFramework \Bootstrap \IBootstrap ;
2627use OCP \AppFramework \Bootstrap \IRegistrationContext ;
2728use OCP \IL10N ;
2829use OCP \IRequest ;
30+ use OCP \ISession ;
2931use OCP \IURLGenerator ;
3032use OCP \IUserManager ;
3133use OCP \IUserSession ;
34+ use OCP \Security \ISecureRandom ;
35+
36+ // this is needed only for the special, shortened client login flow
37+ use Psr \Container \ContainerInterface ;
3238use Throwable ;
3339
3440class Application extends App implements IBootstrap {
@@ -43,14 +49,23 @@ public function __construct(array $urlParams = []) {
4349 }
4450
4551 public function register (IRegistrationContext $ context ): void {
52+ // Register the composer autoloader required for the added jwt-token libs
53+ include_once __DIR__ . '/../../vendor/autoload.php ' ;
54+
55+ // override registration of provisioning srevice to use event-based solution
56+ $ this ->getContainer ()->registerService (ProvisioningService::class, function (ContainerInterface $ c ): ProvisioningService {
57+ return $ c ->get (ProvisioningEventService::class);
58+ });
59+
4660 /** @var IUserManager $userManager */
4761 $ userManager = $ this ->getContainer ()->get (IUserManager::class);
4862
4963 /* Register our own user backend */
50- $ this ->backend = $ this ->getContainer ()->get (Backend::class);
64+ // $this->backend = $this->getContainer()->get(Backend::class);
65+ $ this ->backend = $ this ->getContainer ()->get (MBackend::class);
5166 // this was done before but OC_User::useBackend calls OC::$server->getUserManager()->registerBackend anyway
5267 // so the backend was registered twice, leading to wrong user count (double)
53- // $userManager->registerBackend($this->backend);
68+ $ userManager ->registerBackend ($ this ->backend );
5469 // TODO check if it can be replaced by $userManager->registerBackend($this->backend); in our case
5570 OC_User::useBackend ($ this ->backend );
5671
@@ -70,12 +85,69 @@ public function boot(IBootContext $context): void {
7085 try {
7186 $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerRedirect ' ]));
7287 $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerLogin ' ]));
88+ // this is the custom auto-redirect for MagentaCLOUD client access
89+ $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerNmcClientFlow ' ]));
7390 } catch (Throwable $ e ) {
7491 }
7592 }
7693
77- private function checkLoginToken (TokenService $ tokenService ): void {
78- $ tokenService ->checkLoginToken ();
94+ /**
95+ * This is the automatic redirect exclusively for Nextcloud/Magentacloud clients completely skipping consent layer
96+ */
97+ private function registerNmcClientFlow (IRequest $ request ,
98+ IURLGenerator $ urlGenerator ,
99+ ProviderMapper $ providerMapper ,
100+ ISession $ session ,
101+ ISecureRandom $ random ): void {
102+ $ providers = $ this ->getCachedProviders ($ providerMapper );
103+
104+ // Handle immediate redirect on client first-time login
105+ $ isClientLoginFlow = false ;
106+
107+ try {
108+ $ isClientLoginFlow = $ request ->getPathInfo () === '/login/flow ' ;
109+ } catch (Exception $ e ) {
110+ // in case any errors happen when checking for the path do not apply redirect logic as it is only needed for the login
111+ }
112+
113+ if ($ isClientLoginFlow ) {
114+ // only redirect if Telekom provider registered
115+ $ tproviders = array_values (array_filter ($ providers , function ($ p ) {
116+ return strtolower ($ p ->getIdentifier ()) === 'telekom ' ;
117+ }));
118+
119+ if (count ($ tproviders ) == 0 ) {
120+ // always show normal login flow as error fallback
121+ return ;
122+ }
123+
124+ $ stateToken = $ random ->generate (64 , ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS );
125+ $ session ->set ('client.flow.state.token ' , $ stateToken );
126+
127+ // call the service to get the params, but suppress the template
128+ // compute grant redirect Url to go directly to Telekom login
129+ $ redirectUrl = $ urlGenerator ->linkToRoute ('core.ClientFlowLogin.grantPage ' , [
130+ 'stateToken ' => $ stateToken ,
131+ // grantPage service operation is deriving oauth2 client name (again),
132+ // so we simply pass on clientIdentifier or empty string
133+ 'clientIdentifier ' => $ request ->getParam ('clientIdentifier ' , '' ),
134+ 'direct ' => $ request ->getParam ('direct ' , '0 ' )
135+ ]);
136+
137+ if ($ redirectUrl === null ) {
138+ // always show normal login flow as error fallback
139+ return ;
140+ }
141+
142+ // direct login, consent layer later
143+ $ targetUrl = $ urlGenerator ->linkToRoute (self ::APP_ID . '.login.login ' , [
144+ 'providerId ' => $ tproviders [0 ]->getId (),
145+ 'redirectUrl ' => $ redirectUrl
146+ ]);
147+
148+ header ('Location: ' . $ targetUrl );
149+ exit ();
150+ }
79151 }
80152
81153 private function registerRedirect (IRequest $ request , IURLGenerator $ urlGenerator , SettingsService $ settings , ProviderMapper $ providerMapper ): void {
0 commit comments