3333use OCA \UserOIDC \Listener \TimezoneHandlingListener ;
3434use OCA \UserOIDC \Service \ID4MeService ;
3535use OCA \UserOIDC \Service \SettingsService ;
36- use OCA \UserOIDC \User \Backend ;
36+ use OCA \UserOIDC \Service \ProvisioningService ;
37+ use OCA \UserOIDC \Service \ProvisioningEventService ;
38+ use OCA \UserOIDC \MagentaBearer \MBackend ;
3739use OCP \AppFramework \App ;
3840use OCP \AppFramework \Bootstrap \IBootContext ;
3941use OCP \AppFramework \Bootstrap \IBootstrap ;
4446use OCP \IUserManager ;
4547use OCP \IUserSession ;
4648use Throwable ;
49+ use Psr \Container \ContainerInterface ;
50+
51+ // this is needed only for the special, shortened client login flow
52+ use OCP \Security \ISecureRandom ;
53+ use OCP \ISession ;
4754
4855class Application extends App implements IBootstrap {
4956 public const APP_ID = 'user_oidc ' ;
@@ -57,11 +64,19 @@ public function __construct(array $urlParams = []) {
5764 }
5865
5966 public function register (IRegistrationContext $ context ): void {
67+ // Register the composer autoloader required for the added jwt-token libs
68+ include_once __DIR__ . '/../../vendor/autoload.php ' ;
69+
70+ // override registration of provisioning srevice to use event-based solution
71+ $ this ->getContainer ()->registerService (ProvisioningService::class, function (ContainerInterface $ c ): ProvisioningService {
72+ return $ c ->get (ProvisioningEventService::class);
73+ });
74+
6075 /** @var IUserManager $userManager */
6176 $ userManager = $ this ->getContainer ()->get (IUserManager::class);
6277
6378 /* Register our own user backend */
64- $ this ->backend = $ this ->getContainer ()->get (Backend ::class);
79+ $ this ->backend = $ this ->getContainer ()->get (MBackend ::class);
6580 $ userManager ->registerBackend ($ this ->backend );
6681 OC_User::useBackend ($ this ->backend );
6782
@@ -79,10 +94,70 @@ public function boot(IBootContext $context): void {
7994 try {
8095 $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerRedirect ' ]));
8196 $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerLogin ' ]));
97+ // this is the custom auto-redirect for MagentaCLOUD client access
98+ $ context ->injectFn (\Closure::fromCallable ([$ this , 'registerNmcClientFlow ' ]));
8299 } catch (Throwable $ e ) {
83100 }
84101 }
85102
103+ /**
104+ * This is the automatic redirect exclusively for Nextcloud/Magentacloud clients
105+ * completely skipping consent layer
106+ */
107+ private function registerNmcClientFlow (IRequest $ request ,
108+ IURLGenerator $ urlGenerator ,
109+ ProviderMapper $ providerMapper ,
110+ ISession $ session ,
111+ ISecureRandom $ random ): void {
112+ $ providers = $ this ->getCachedProviders ($ providerMapper );
113+
114+ // Handle immediate redirect on client first-time login
115+ $ isClientLoginFlow = false ;
116+ try {
117+ $ isClientLoginFlow = $ request ->getPathInfo () === '/login/flow ' ;
118+ } catch (Exception $ e ) {
119+ // in case any errors happen when checking for the path do not apply redirect logic as it is only needed for the login
120+ }
121+ if ($ isClientLoginFlow ) {
122+ // only redirect if Telekom provider registered
123+ $ tproviders = array_values (array_filter ($ providers , function ($ p ) {
124+ return strtolower ($ p ->getIdentifier ()) === "telekom " ;
125+ }));
126+ if (count ($ tproviders ) == 0 ) {
127+ // always show normal login flow as error fallback
128+ return ;
129+ }
130+
131+ $ stateToken = $ random ->generate (
132+ 64 ,
133+ ISecureRandom::CHAR_LOWER .ISecureRandom::CHAR_UPPER .ISecureRandom::CHAR_DIGITS
134+ );
135+ $ session ->set ('client.flow.state.token ' , $ stateToken );
136+
137+ // call the service to get the params, but suppress the template
138+ // compute grant redirect Url to go directly to Telekom login
139+ $ redirectUrl = $ urlGenerator ->linkToRoute ('core.ClientFlowLogin.grantPage ' , [
140+ 'stateToken ' => $ stateToken ,
141+ // grantPage service operation is deriving oauth2 client name (again),
142+ // so we simply pass on clientIdentifier or empty string
143+ 'clientIdentifier ' => $ request ->getParam ('clientIdentifier ' , '' ),
144+ 'direct ' => $ request ->getParam ('direct ' , '0 ' )
145+ ]);
146+ if ($ redirectUrl === null ) {
147+ // always show normal login flow as error fallback
148+ return ;
149+ }
150+
151+ // direct login, consent layer later
152+ $ targetUrl = $ urlGenerator ->linkToRoute (self ::APP_ID . '.login.login ' , [
153+ 'providerId ' => $ tproviders [0 ]->getId (),
154+ 'redirectUrl ' => $ redirectUrl
155+ ]);
156+ header ('Location: ' . $ targetUrl );
157+ exit ();
158+ }
159+ }
160+
86161 private function registerRedirect (IRequest $ request , IURLGenerator $ urlGenerator , SettingsService $ settings , ProviderMapper $ providerMapper ): void {
87162 $ providers = $ this ->getCachedProviders ($ providerMapper );
88163 $ redirectUrl = $ request ->getParam ('redirect_url ' );
0 commit comments