expo AuthSession with Keycloak signed with letsencrypt free SSL certificate, returns error when trying to exchange code to get JWT on android

Viewed 33

I am building an app with react native using expo and I'm handling authentication with Keycloak that was signed with a certificate from letsencrypt so as to use HTTPS. I am able to retrieve the token without issue from a web browser, from postman, and from the app running on an iphone, but I have issue with android as it returns me this not so helpful error:

Error: An unknown error occurred

Here is my code for the authentication flow of keycloak:

import React from "react";
import {
  makeRedirectUri,
  useAuthRequest,
  exchangeCodeAsync,
  CodeChallengeMethod,
} from "expo-auth-session";
import { Button, View, StyleSheet } from "react-native";

// WebBrowser.maybeCompleteAuthSession();

const discovery = {
  authorizationEndpoint:
    "https://<MY DOMAIN SIGNED BY LETSENCRYPT>/protocol/openid-connect/auth",
  tokenEndpoint:
    "https://<MY DOMAIN SIGNED BY LETSENCRYPT>/protocol/openid-connect/token",
};

export default function App() {
  const [secretCode, setSecretCode] = React.useState("");

  const [request, response, promptAsync] = useAuthRequest(
    {
      clientId: "<MY CLIENT ID>",
      redirectUri: makeRedirectUri({}),
      usePKCE: true,
      codeChallenge: "",
      codeChallengeMethod: CodeChallengeMethod.S256,
      responseType: "code",
      // state: code_state,
    },
    discovery
  );

  React.useEffect(() => {
    if (response?.type === "success") {
      const { code } = response.params;
      setSecretCode(code);
      console.log("code :>> ", code);
    }
  }, [response]);

  const getToken = async () => {
    try {
      const requestToken = exchangeCodeAsync(
        {
          code: secretCode,
          redirectUri: makeRedirectUri({}),
          clientId: "<MY CLIENT ID>",
          clientSecret: "<MY CLIENT SECRET>",
          extraParams: {
            code_verifier: request?.codeVerifier ? request?.codeVerifier : "",
          },
        },
        discovery
      );
      console.log("requestToken :>> ", requestToken);
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <View style={styles.container}>
      <View>
        <Button
          disabled={!request}
          title="Login"
          onPress={() => {
            promptAsync();
          }}
        />
      </View>
      {response && <Button title="Obtain Token" onPress={() => getToken()} />}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

This has frustrated me for a month as I did find on the internet people who have the same issue as me but not resolution to the problem.

If there are any missing information needed that I may have forgotten to help find a solution I am more than happy to provide it. Thank you.

0 Answers
Related