Skip to content

ClassCastException: LinkedTreeMap cannot be cast to String when ID token claims contain JSON objects instead of strings #830

@mjgasiorfp

Description

@mjgasiorfp

Checklist

Description

Description

When a user authenticates via a social provider that returns standard OIDC claims (such as picture or profile) as JSON objects rather than plain strings, the Android SDK crashes with a fatal ClassCastException immediately after login.

Steps to Reproduce

  1. Set up Auth0 with a social connection where the user profile stores picture (or profile) as a JSON object, e.g. {"url": "https://...", "type": "image/jpeg"} rather than a plain string URL
  2. Call auth0.webAuthentication(scheme: '...').login() on Android
  3. App crashes immediately after the browser closes

Error

FATAL EXCEPTION: main
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.lang.String
    at com.auth0.auth0_flutter.UserProfileExtensionsKt.getProfileURL(UserProfileExtensions.kt:42)
    at com.auth0.auth0_flutter.UserProfileExtensionsKt.toMap(UserProfileExtensions.kt:15)
    at com.auth0.auth0_flutter.request_handlers.web_auth.LoginWebAuthRequestHandler$handle$1.onSuccess(LoginWebAuthRequestHandler.kt:95)

Root Cause

UserProfileExtensions.kt uses unsafe Kotlin casts (as String?) for all standard OIDC string claims. When GSON parses a JSON object value it produces a LinkedTreeMap, and as String? throws ClassCastException on any non-null non-String value (unlike as? String which would safely return null).

Affected properties: profileURL, websiteURL, gender, birthdate, zoneinfo, locale, phoneNumber, updatedAt, middleName, preferredUsername — and pictureURL via the underlying auth0-android UserProfile class.

Expected Behaviour

Claims that are unexpectedly non-string values should be treated as null rather than crashing the app.

Suggested Fix

Change all as String? (unsafe nullable cast) to as? String (safe cast) in UserProfileExtensions.kt, and read picture directly from getExtraInfo() to bypass the base class property:

fun UserProfile.toMap(): Map<String, Any?> {
    return mapOf(
        ...
        "picture" to (this.getExtraInfo()["picture"] as? String),
        ...
    )
}

val UserProfile.profileURL: String?
    get() = getExtraInfo()["profile"] as? String

val UserProfile.middleName: String?
    get() = getExtraInfo()["middle_name"] as? String

// ... same pattern for all other String? extension properties

Environment

  • auth0_flutter: 2.1.0-beta.1
  • Android (Samsung Galaxy S21)
  • Social connection returning picture / profile as JSON object

File it at: https://github.com/auth0/auth0-flutter/issues/new

Reproduction

  1. Set up Auth0 with a social connection where the user profile stores picture or profile as a JSON object (e.g. {"url": "https://..."}) rather than a plain string URL
  2. Call auth0.webAuthentication(scheme: '...').login() on Android
  3. App crashes immediately after the browser closes and the SDK tries to build the UserProfile

Additional context

The crash also occurs on the profile claim, not just picture. Any standard OIDC claim that a social provider returns as a JSON object instead of a string will trigger this. The underlying issue is GSON deserialising JSON objects as LinkedTreeMap, which then cannot be cast with as String?.

auth0_flutter version

2.1.0-beta.1

Flutter version

3.41.9

Platform

Android

Platform version(s)

Android 13 (Samsung Galaxy S21)

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions