88use Drupal \Core \Controller \ControllerBase ;
99use Drupal \Core \Logger \RfcLogLevel ;
1010use Drupal \Core \Url ;
11+ use Drupal \os2loop_cura_login \CuraHelper ;
12+ use Drupal \os2loop_cura_login \IdPHelper ;
1113use Drupal \os2loop_cura_login \Settings ;
14+ use Drupal \os2loop_cura_login \UserHelper ;
1215use Drupal \user \UserInterface ;
13- use Drupal \user \UserStorageInterface ;
1416use Firebase \JWT \JWT ;
15- use Firebase \JWT \Key ;
1617use Psr \Log \LoggerInterface ;
1718use Psr \Log \LoggerTrait ;
1819use Psr \Log \LogLevel ;
@@ -30,21 +31,18 @@ final class Os2loopCuraLoginController extends ControllerBase {
3031
3132 private const JWT_KEY = 'os2loop_cura_login ' ;
3233
33- /**
34- * The user storage.
35- */
36- private readonly UserStorageInterface $ userStorage ;
37-
3834 /**
3935 * Constructor.
4036 */
4137 public function __construct (
38+ private readonly CuraHelper $ curaHelper ,
39+ private readonly IdPHelper $ idPHelper ,
40+ private readonly UserHelper $ userHelper ,
4241 private readonly Settings $ settings ,
4342 private readonly TimeInterface $ time ,
4443 #[Autowire(service: 'logger.channel.os2loop_cura_login ' )]
4544 private readonly LoggerInterface $ logger ,
4645 ) {
47- $ this ->userStorage = $ this ->entityTypeManager ()->getStorage ('user ' );
4846 }
4947
5048 /**
@@ -68,7 +66,7 @@ public function start(Request $request, ?string $jwt): Response {
6866 ]);
6967
7068 if (empty ($ jwt )) {
71- $ name = $ this ->settings ->getPayloadName ();
69+ $ name = $ this ->settings ->getCuraSettings ()-> getPayloadName ();
7270 $ jwt = Request::METHOD_POST === $ request ->getMethod ()
7371 ? $ request ->request ->getString ($ name )
7472 : $ request ->query ->getString ($ name );
@@ -84,21 +82,14 @@ public function start(Request $request, ?string $jwt): Response {
8482 throw new BadRequestHttpException ('Missing or empty JWT ' );
8583 }
8684
87- $ payload = $ this ->decodeJwt ($ jwt );
88-
89- $ this ->debug ('@debug ' , [
90- '@debug ' => json_encode ([
91- 'payload ' => $ payload ,
92- ]),
93- ]);
85+ [$ payload , $ username ] = $ this ->curaHelper ->decodeJwt ($ jwt );
9486
95- $ username = $ payload ['username ' ] ?? $ payload ['brugerId ' ] ?? NULL ;
9687 if (empty ($ username )) {
9788 throw new BadRequestHttpException ('Missing username ' );
9889 }
9990
10091 // Check that we can get userinfo.
101- $ userinfo = $ this ->fetchUserinfo ($ username );
92+ $ userinfo = $ this ->idPHelper -> fetchUserInfo ($ username );
10293
10394 $ this ->debug ('@debug ' , [
10495 '@debug ' => json_encode ([
@@ -111,7 +102,7 @@ public function start(Request $request, ?string $jwt): Response {
111102 throw new BadRequestHttpException ();
112103 }
113104
114- $ user = $ this ->ensureUser ($ username , $ userinfo );
105+ $ user = $ this ->userHelper -> ensureUser ($ username , $ userinfo );
115106
116107 $ this ->debug ('@debug ' , [
117108 '@debug ' => json_encode ([
@@ -134,44 +125,22 @@ public function start(Request $request, ?string $jwt): Response {
134125 }
135126 }
136127
137- /**
138- * Create authenticate response.
139- */
140- private function createAuthenticateResponse (UserInterface $ user ): Response {
141- // https://github.com/firebase/php-jwt?tab=readme-ov-file#example
142- $ payload = [
143- // Issued at.
144- 'iat ' => $ this ->time ->getRequestTime (),
145- // Expire af 60 seconds.
146- 'exp ' => $ this ->time ->getRequestTime () + 60 ,
147- 'username ' => $ user ->getAccountName (),
148- ];
149- $ jwt = $ this ->encodeJwt ($ payload );
150-
151- $ url = Url::fromRoute ('os2loop_cura_login.authenticate ' , [
152- 'jwt ' => $ jwt ,
153- ])->setAbsolute ()->toString (TRUE )->getGeneratedUrl ();
154-
155- return new Response ($ url );
156- }
157-
158128 /**
159129 * Authenticate action.
160130 */
161- public function authenticate (Request $ request ): Response {
131+ public function authenticate (Request $ request, string $ jwt ): Response {
162132 try {
163- $ jwt = $ request ->get ('jwt ' );
164133 if (empty ($ jwt )) {
165134 throw new BadRequestHttpException ();
166135 }
167136
168- $ payload = $ this ->decodeJwt ($ jwt );
137+ [ $ payload, $ _ ] = $ this -> curaHelper ->decodeJwt ($ jwt );
169138 $ username = $ payload ['username ' ] ?? NULL ;
170139 if (empty ($ username )) {
171140 throw new BadRequestHttpException ();
172141 }
173142
174- $ user = $ this ->loadUser ($ username );
143+ $ user = $ this ->userHelper -> loadUser ($ username );
175144 if (empty ($ user )) {
176145 // Don't disclose whether or not the user exists.
177146 throw new BadRequestHttpException ();
@@ -185,6 +154,27 @@ public function authenticate(Request $request): Response {
185154 }
186155 }
187156
157+ /**
158+ * Create authenticate response.
159+ */
160+ private function createAuthenticateResponse (UserInterface $ user ): Response {
161+ // https://github.com/firebase/php-jwt?tab=readme-ov-file#example
162+ $ payload = [
163+ // Issued at.
164+ 'iat ' => $ this ->time ->getRequestTime (),
165+ // Expire af 60 seconds.
166+ 'exp ' => $ this ->time ->getRequestTime () + 60 ,
167+ 'username ' => $ user ->getAccountName (),
168+ ];
169+ $ jwt = $ this ->encodeJwt ($ payload );
170+
171+ $ url = Url::fromRoute ('os2loop_cura_login.authenticate ' , [
172+ 'jwt ' => $ jwt ,
173+ ])->setAbsolute ()->toString (TRUE )->getGeneratedUrl ();
174+
175+ return new Response ($ url );
176+ }
177+
188178 /**
189179 * Authenticate user.
190180 */
@@ -200,99 +190,9 @@ private function authenticateUser($user): Response {
200190 * Encode JWT.
201191 */
202192 private function encodeJwt (array $ payload ): string {
203- $ secret = $ this ->settings ->getSigningSecret ();
204- // @todo Get rid of the double base64 encoding.
205- $ secret = base64_decode ($ secret );
206-
207- return JWT ::encode ($ payload , $ secret , $ this ->settings ->getSigningAlgorithm ());
208- }
209-
210- /**
211- * Decode JWT.
212- */
213- private function decodeJwt (string $ jwt ): array {
214- $ secret = $ this ->settings ->getSigningSecret ();
215- // @todo Get rid of the double base64 encoding.
216- $ secret = base64_decode ($ secret );
217-
218- $ originalLeeway = JWT ::$ leeway ;
219- $ leeway = $ this ->settings ->getJwtLeeway ();
220- if ($ leeway > 0 ) {
221- JWT ::$ leeway = $ leeway ;
222- }
223- $ payload = (array ) JWT ::decode ($ jwt , new Key ($ secret , $ this ->settings ->getSigningAlgorithm ()));
224- JWT ::$ leeway = $ originalLeeway ;
225-
226- return $ payload ;
227- }
228-
229- /**
230- * Get user info from userinfo endpoint.
231- */
232- private function fetchUserinfo (string $ username ): array {
233- return [
234- // Drupal user fields.
235- 'name ' => $ username ,
236- 'mail ' => $ username . '@cura.example.com ' ,
237-
238- // OS2Lloop fields
239- // 'os2loop_user_address' => '',
240- // 'os2loop_user_areas_of_expertise' => '',
241- // 'os2loop_user_biography' => '',
242- // 'os2loop_user_city' => '',
243- // 'os2loop_user_external_list' => '',.
244- 'os2loop_user_family_name ' => 'Cura ' ,
245- 'os2loop_user_given_name ' => 'User ' ,
246- // 'os2loop_user_image' => '',
247- // 'os2loop_user_internal_list' => '',
248- // 'os2loop_user_job_title' => '',
249- // 'os2loop_user_phone_number' => '',
250- // 'os2loop_user_place' => '',
251- // 'os2loop_user_postal_code' => '',
252- // 'os2loop_user_professions' => '',
253- ];
254- }
255-
256- /**
257- * Ensure user exists.
258- *
259- * @param string $username
260- * The username.
261- * @param array $userinfo
262- * The user info to set on the user.
263- *
264- * @return \Drupal\user\Entity\UserInterface
265- * The newly created or updated user.
266- */
267- private function ensureUser (string $ username , array $ userinfo ): UserInterface {
268- $ user = $ this ->loadUser ($ username );
269-
270- if (NULL === $ user ) {
271- $ user = $ this ->userStorage ->create ();
272- }
273-
274- foreach ($ userinfo as $ field => $ value ) {
275- $ currentValue = $ user ->get ($ field );
276- if ($ currentValue !== $ value ) {
277- $ user ->set ($ field , $ value );
278- }
279- }
280-
281- // Make sure that the user is active.
282- $ user
283- ->activate ()
284- ->save ();
285-
286- return $ user ;
287- }
288-
289- /**
290- * Load user by username.
291- */
292- private function loadUser (string $ username ) : ?UserInterface {
293- $ users = $ this ->userStorage ->loadByProperties (['name ' => $ username ]);
193+ $ settings = $ this ->settings ->getCuraSettings ();
294194
295- return reset ( $ users ) ?: NULL ;
195+ return JWT :: encode ( $ payload , $ settings -> getSigningSecret (), $ settings -> getSigningAlgorithm ()) ;
296196 }
297197
298198 /**
0 commit comments