Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] OAuth login wouldn't get redirected on tablet android devices #2932

Open
1 of 3 tasks
Pheggas opened this issue Jun 24, 2023 · 14 comments · May be fixed by #10832
Open
1 of 3 tasks

[BUG] OAuth login wouldn't get redirected on tablet android devices #2932

Pheggas opened this issue Jun 24, 2023 · 14 comments · May be fixed by #10832
Labels
bug Something isn't working 📱mobile needs triage Bug that needs triage from maintainer

Comments

@Pheggas
Copy link
Contributor

Pheggas commented Jun 24, 2023

The bug

According to our discussion, i'm opening this issue. I have 3 Android tablet devices at home from which none is able to login with OAuth. After i enter correct URL as target server and click Login with OAuth (and in case of having multiple google accounts log in, selecting correct google account), Chrome embeded browser will just close (as it should) and Immich will show the initial screen with target server URL again without properly log me in.

It only happens on tablet devices, not mobile-format one. I've tested it on Android 13, 11 and 7.1.1. I've also did same test on emulated android tablet device and there it worked perfectly. In fact, i've been able to log in with Android 11 tablet device once after disabling Blokada 5 (which is Ad-blocking app for android). Then i logged off and tried the same thing with having Blokada turned on. After this weird bug appearing again, i turned off the Blokada again and tried the login process. Yet the behavior didn't change unexpectedly.

The OS that Immich Server is running on

Ubuntu Server 22.04 LTS

Version of Immich Server

v1.63.0 (first time spotted on v1.62.0)

Version of Immich Mobile App

1.63.0

Platform with the issue

  • Server
  • Web
  • Mobile

Your docker-compose.yml content

version: "3.8"

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    command: ["start-server.sh"]
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
    env_file:
      - stack.env

    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "com.centurylinklabs.watchtower.enable=false"
    depends_on:
      - redis
      - database
      - typesense
    networks:

      - immich
    restart: always

  immich-microservices:
    container_name: immich_microservices
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    command: ["start-microservices.sh"]
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
    env_file:
      - stack.env
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    depends_on:
      - redis
      - database
      - typesense
    networks:
      - immich
    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /home/docker/docker_immich/model-cache:/cache
    env_file:
      - stack.env
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    networks:
      - immich
    restart: always

  immich-web:
    container_name: immich_web
    image: ghcr.io/immich-app/immich-web:${IMMICH_VERSION:-release}
    env_file:
      - stack.env
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    networks:
      - immich
    restart: always

  typesense:
    container_name: immich_typesense
    image: typesense/typesense:0.24.0
    environment:
      - TYPESENSE_API_KEY=${TYPESENSE_API_KEY}
      - TYPESENSE_DATA_DIR=/data
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: none
    volumes:
      - /home/docker/docker_immich/tsdata:/data
    networks:
      - immich
    restart: always

  redis:
    container_name: immich_redis
    image: redis:6.2
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    networks:
      - immich
    restart: always

  database:
    container_name: immich_postgres
    image: postgres:14
    env_file:
      - stack.env
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      PG_DATA: /var/lib/postgresql/data
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks:
      - immich
    volumes:
      - /home/docker/docker_immich/pgdata:/var/lib/postgresql/data
    restart: always

  immich-proxy:
    container_name: immich_proxy
    image: ghcr.io/immich-app/immich-proxy:${IMMICH_VERSION:-release}
    environment:
      # Make sure these values get passed through from the env file
      - IMMICH_SERVER_URL
      - IMMICH_WEB_URL
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
      - "traefik.enable=true"
      - "traefik.http.routers.immich-local.rule=Host(`immich.local.example.eu`)"
      - "traefik.http.routers.immich-local.entrypoints=web, websecure"
      - "traefik.http.routers.immich-local.tls=true"
      - "traefik.http.routers.immich-local.tls.certresolver=cloudflare"
      - "traefik.http.routers.immich-local.tls.domains[0].main=local.example.eu"
      - "traefik.http.routers.immich-local.tls.domains[0].sans=*.local.example.eu"
      - "traefik.http.routers.immich.entrypoints=web, websecure"
      - "traefik.http.routers.immich.rule=Host(`immich.services.example.eu`)"
      - "traefik.http.routers.immich.tls=true"
      - "traefik.http.routers.immich.tls.certresolver=staging"
      - "traefik.docker.network=proxy"
    networks:
      - proxy
      - immich
    ports:
      - 2283:8080
    depends_on:
      - immich-server
    restart: always

networks:
  immich:
  proxy:
    external: true

Your .env content

DB_HOSTNAME=redacted
DB_USERNAME=redacted
DB_PASSWORD=redacted
DB_DATABASE_NAME=redacted
REDIS_HOSTNAME=immich_redis
UPLOAD_LOCATION=/mnt/Backups/immich
TYPESENSE_API_KEY=redacted
PUBLIC_LOGIN_PAGE_MESSAGE="It works!"
IMMICH_WEB_URL=http://immich-web:3000
IMMICH_SERVER_URL=http://immich-server:3001
IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003
TZ=Europe/Bratislava

Reproduction steps

1. Deploy Immich v1.63.0 with Google OAuth
2. Login with mobile-format android device (Working fine)
3. Login with tablet-format android device (Redirecting issue)

Additional information

No response

@Pheggas Pheggas added bug Something isn't working needs triage Bug that needs triage from maintainer labels Jun 24, 2023
@qrkourier
Copy link

qrkourier commented Jul 3, 2024

I may have stumbled upon a fix for Android.

I stumbled upon it because I'm using Auth0 who do not accept custom schemes with the precise shape used by Immich in their input validation for callbacks, i.e. app.immich:/ is invalid, so it's impossible to configure Immich to so that the mobile app initiates the flow with a valid callback.

I discovered that by adding two forward slashes to the requested callback (it can be modified because it's not part of the signed payload) then two necessary things happen: the IdP accepts the callback (as long as app.immich:/// is authorized in the app settings), and app.immich:/// correctly redirects to the mobile app to conclude the interactive client flow.

In summary, if there were a toggle in Immich admin to configure the mobile client to request a callback on app.immich:/// then it's only necessary for the IdP to allow that URL, or a redirector that responds with HTTP header location: app.immich:///.

@qrkourier
Copy link

I partially worked around the Auth0 limitation on iOS in the same way. I captured the initiating auth request URL with the requested callback and modified it to match the one that's allowed by Auth0, app.immich:///.

The flow succeeds until the redirect is finally called and app.immich:/// doesn't resolve to an app launcher registration in iOS, so presumably Immich is hard-coded to suit iOS devices that expect a custom scheme with only one forward slash like app.immich:/.

If I change Immich to use a mobile URI override that responds with location: app.immich:/ then the iOS app is launched but the concluding step of the client flow is lost somehow, and so the iOS app only displays the login form as was originally reported here for the Android devices.

It seems the problem is universal to mobile-initiated OAuth, and possibly limited to cases where the mobile URI override is necessary.

@jrasm91
Copy link
Contributor

jrasm91 commented Jul 4, 2024

That scheme has always looked weird to me. Is it normal? Should it really have two forward slashes instead?

@qrkourier
Copy link

qrkourier commented Jul 4, 2024

app.immich:/ is not a complete URI scheme. It's missing a trailing slash. The meaning of location: app.immich:/// should be interpreted as "the root resource for app.immich" e.g., file:/// means / in the filesystem.

There's probably some historical reason why app.immich:/ is too painful to change without protest, so the only paths forward I see are redress the mobile callback so that it's compatible with both iOS and Android or branch the logic to handle each separately.

@jrasm91
Copy link
Contributor

jrasm91 commented Jul 4, 2024

Honestly, I'd be fine changing it from app.immich:/ to app.immich:// as long as that is more correct, standard, and is proven to be the fix for this issue.

@qrkourier
Copy link

Cool. I'm testing the change for Android. Can someone tell me how or help with testing in iOS? I have an old iPhone SE.

@qrkourier qrkourier linked a pull request Jul 4, 2024 that will close this issue
@Pheggas
Copy link
Contributor Author

Pheggas commented Jul 4, 2024

Damn. I can't believe this is actually getting resolved (hopefully). Fingers crossed!

@qrkourier
Copy link

qrkourier commented Jul 4, 2024

Does anyone have a Flutter env set up on macOS? I'm guessing that we've built and tested manually for iOS because the mobile build workflow targets only Android.

It would be good to have a few more Android testers at least, too. @Pheggas will you loan one of your Android devices to this cause by installing the test build (link may require GitHub login)?

To test, uninstall the Immich app and unzip the download. If you can't find a way to do it on mobile then attach Android device with USB and enable developer option USB debugging so you can run adb install app-release.apk on the laptop to install Immich test build on the Android device.

@Pheggas
Copy link
Contributor Author

Pheggas commented Jul 4, 2024

@Pheggas will you loan one of your Android devices to this cause by installing the test build (link may require GitHub login)?

Sure. I already did and it does exactly the same thing it did before. Is there something i should alter in the setup in order to have correct setup?

For your information, i have configured Google OAuth for mobile using this method. And as it points to app.immich:/, which is not the correct format (according to this conversation), it probably shouldn't work by now (?)

@qrkourier
Copy link

qrkourier commented Jul 5, 2024

To confirm, you installed the experimental "release" APK from this branch that changes the requested callback to app.immich:///. Your Google OAuth client is configured to allow callback URI app.immich:/// in the web application credential settings in "Authorized redirect URIs."

With this configuration, you still experience the following symptom after successfully authenticating with Google on an Android tablet device: there are no errors, and the experimental build of the Immich app is launched, but not logged in. Instead, the login screen or server URL form are displayed, as if the token was not successfully passed to the app.

The Immich app has a "logs" link at the bottom of the UI. Will you see if there are any clues there about why the final oauth step failed?

@Pheggas
Copy link
Contributor Author

Pheggas commented Jul 9, 2024

Your Google OAuth client is configured to allow callback URI app.immich:/// in the web application credential settings in "Authorized redirect URIs."

Sorry for late reply. I tried to add app.immich:/// to the authorized redirect URIs but it throws error:
image

That's why i didn't follow the default option with app.immich:/. Could you provide me some workaroud how could i fix this issue? Related to #1174

Full list of URIs:
image

@qrkourier
Copy link

qrkourier commented Jul 9, 2024

This tells me Google OAuth requires only standard, not custom, URI schemes, so it's necessary to utilize Immich's URI redirector feature with Google.

For example, configure Google OAuth with authorized redirect URI https://immich.example.eu/api/oauth/mobile-redirect, and ensure Immich's URI redirector is set to app.immich:/// by installing the Immich server built from PR branch associated with this GitHub issue: https://github.com/qrkourier/immich/tree/mobile-oauth-scheme

@Pheggas
Copy link
Contributor Author

Pheggas commented Jul 9, 2024

As i don't want to mess up my existing setup, i'll spin up new instance with immich and reply you with results. This would take some time (days) so please, be patient. I'll let you know.

@qrkourier
Copy link

qrkourier commented Jul 9, 2024

Wonderful. Thank you for the assist. I found that Immich's endpoint /api/oauth/mobile-redirect is already enabled, so you can skip the step to configure a custom URI redirector. /api/oauth/mobile-redirect for the experimental Immich server in this branch always redirects to app.immich:///, so it works around the issue where some OAuth providers, like Google, do not permit custom schemes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working 📱mobile needs triage Bug that needs triage from maintainer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants