@@ -17,15 +17,17 @@ const authServer = {
17
17
external : 'http://127.0.0.1:3000' ,
18
18
} ;
19
19
20
+ const mobileOverrideRedirectUri = 'https://photos.immich.app/oauth/mobile-redirect' ;
21
+
20
22
const redirect = async ( url : string , cookies ?: string [ ] ) => {
21
23
const { headers } = await request ( url )
22
24
. get ( '/' )
23
25
. set ( 'Cookie' , cookies || [ ] ) ;
24
26
return { cookies : ( headers [ 'set-cookie' ] as unknown as string [ ] ) || [ ] , location : headers . location } ;
25
27
} ;
26
28
27
- const loginWithOAuth = async ( sub : OAuthUser | string ) => {
28
- const { url } = await startOAuth ( { oAuthConfigDto : { redirectUri : `${ baseUrl } /auth/login` } } ) ;
29
+ const loginWithOAuth = async ( sub : OAuthUser | string , redirectUri ?: string ) => {
30
+ const { url } = await startOAuth ( { oAuthConfigDto : { redirectUri : redirectUri ?? `${ baseUrl } /auth/login` } } ) ;
29
31
30
32
// login
31
33
const response1 = await redirect ( url . replace ( authServer . internal , authServer . external ) ) ;
@@ -255,4 +257,50 @@ describe(`/oauth`, () => {
255
257
} ) ;
256
258
} ) ;
257
259
} ) ;
260
+
261
+ describe ( 'mobile redirect override' , ( ) => {
262
+ beforeAll ( async ( ) => {
263
+ await setupOAuth ( admin . accessToken , {
264
+ enabled : true ,
265
+ clientId : OAuthClient . DEFAULT ,
266
+ clientSecret : OAuthClient . DEFAULT ,
267
+ buttonText : 'Login with Immich' ,
268
+ storageLabelClaim : 'immich_username' ,
269
+ mobileOverrideEnabled : true ,
270
+ mobileRedirectUri : mobileOverrideRedirectUri ,
271
+ } ) ;
272
+ } ) ;
273
+
274
+ it ( 'should return the mobile redirect uri' , async ( ) => {
275
+ const { status, body } = await request ( app )
276
+ . post ( '/oauth/authorize' )
277
+ . send ( { redirectUri : 'app.immich:///oauth-callback' } ) ;
278
+ expect ( status ) . toBe ( 201 ) ;
279
+ expect ( body ) . toEqual ( { url : expect . stringContaining ( `${ authServer . internal } /auth?` ) } ) ;
280
+
281
+ const params = new URL ( body . url ) . searchParams ;
282
+ expect ( params . get ( 'client_id' ) ) . toBe ( 'client-default' ) ;
283
+ expect ( params . get ( 'response_type' ) ) . toBe ( 'code' ) ;
284
+ expect ( params . get ( 'redirect_uri' ) ) . toBe ( mobileOverrideRedirectUri ) ;
285
+ expect ( params . get ( 'state' ) ) . toBeDefined ( ) ;
286
+ } ) ;
287
+
288
+ it ( 'should auto register the user by default' , async ( ) => {
289
+ const url = await loginWithOAuth ( 'oauth-mobile-override' , 'app.immich:///oauth-callback' ) ;
290
+ expect ( url ) . toEqual ( expect . stringContaining ( mobileOverrideRedirectUri ) ) ;
291
+
292
+ // simulate redirecting back to mobile app
293
+ const redirectUri = url . replace ( mobileOverrideRedirectUri , 'app.immich:///oauth-callback' ) ;
294
+
295
+ const { status, body } = await request ( app ) . post ( '/oauth/callback' ) . send ( { url : redirectUri } ) ;
296
+ expect ( status ) . toBe ( 201 ) ;
297
+ expect ( body ) . toMatchObject ( {
298
+ accessToken : expect . any ( String ) ,
299
+ isAdmin : false ,
300
+ name : 'OAuth User' ,
301
+
302
+ userId : expect . any ( String ) ,
303
+ } ) ;
304
+ } ) ;
305
+ } ) ;
258
306
} ) ;
0 commit comments