-
Notifications
You must be signed in to change notification settings - Fork 10
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
馃悰 Bug Report: React Native - createOAuth2Session throws error #10
Comments
I would like to work on this issue please |
This is where the error occurs: Looks like href is read only in react native |
I try but don't show login form of google. Please check. Thanks |
React-native can't just open a web url. The Appwrite SDK was designed for web browsers, which make redirections, and for that reason certain parts like OAuth authentication won't work out of the box in react-native. There are a few ways around this though:
Hope this helps Note: this might be relevant for issue #1177797467 |
I was looking for a solution to avoid closed common other backend services. |
We're working a new dedicated React Native SDK. Moving this issue to the new repository |
Hey, nice that you're putting some efforts on a dedicated react-native sdk! :) Turns out that I've been trying appwrite in a RN app and this was the first thing that I came across. I managed to workaround the issue for now by overriding the I've used If anybody's interested on it until it's implemented in the sdk, here are my snippets: Use at your own risk!/lib/appwrite/account.tsimport * as WebBrowser from "expo-web-browser";
import { Account, AppwriteException, OAuthProvider } from "appwrite";
import { handleIncomingCookie } from "./handleIncomingCookie";
import { buildQueryParams } from "./uri";
export class OauthAwareAccount extends Account {
/**
* @deprecated Temporaryly use {@link createOAuthSession} instead, can't use this because of its return type (not a promise)
* @param provider
* @param success
* @param failure
* @param scopes
* @returns
*/
override createOAuth2Session(
provider: OAuthProvider,
success?: string | undefined,
failure?: string | undefined,
scopes?: string[] | undefined,
): void | URL {
return super.createOAuth2Session(provider, success, failure, scopes);
}
async createOAuthSession(
provider: OAuthProvider,
success?: string | undefined,
failure?: string | undefined,
scopes?: string[] | undefined,
): Promise<void | URL> {
if (!provider) {
throw new AppwriteException('Missing required parameter: "provider"');
}
const { endpoint, project } = this.client.config;
const apiPath = `/account/sessions/oauth2/${provider}`;
const payload: Record<string, string | string[] | undefined> = {
success,
failure,
scopes,
project,
};
const queryParams = buildQueryParams(payload);
const authUrl = `${endpoint}${apiPath}${queryParams ? `?${queryParams}` : ""}`;
const callbackUrl = `appwrite-callback-${project}`;
const browserResult = await WebBrowser.openAuthSessionAsync(
authUrl,
callbackUrl,
);
if (browserResult.type !== "success") {
return;
}
const url = browserResult.url;
if (!(await handleIncomingCookie(url, endpoint))) {
return;
}
return new URL(url);
}
} /lib/appwrite/handleIncomingCookie.tsimport CookieManager, { Cookie } from "@react-native-cookies/cookies";
import { AppwriteException } from "appwrite";
import { parseQueryParams } from "./uri";
export const handleIncomingCookie = async (url: string, endpoint: string) => {
if (!url.includes("appwrite-callback")) {
return false;
}
const queryParams = parseQueryParams(url);
if (!queryParams.key || !queryParams.secret || !queryParams.domain) {
throw new AppwriteException(
"Invalid OAuth2 Response. Key, Secret and Domain not available.",
500,
);
}
const domainUrl = new URL(endpoint);
const cookie: Cookie = {
name: queryParams.key,
value: queryParams.secret,
path: queryParams.path,
expires: queryParams.expires,
secure: "secure" in queryParams,
httpOnly: "httpOnly" in queryParams,
domain: domainUrl.hostname,
};
return CookieManager.set(domainUrl.toString(), cookie);
}; /lib/appwrite/uri.tsThe sdk has some utilities for this already, like export const buildQueryParams = (
params: Record<string, string | string[] | undefined>,
) =>
Object.keys(params).reduce((acc, currentKey) => {
const currentValueForKey = params[currentKey];
if (currentValueForKey === undefined) {
return acc;
}
if (Array.isArray(currentValueForKey)) {
const arrayQuery = currentValueForKey
.map(
(value) =>
`${encodeURIComponent(`${currentKey}[]`)}=${encodeURIComponent(value)}`,
)
.join("&");
return `${acc}&${arrayQuery}`;
}
return `${acc}&${encodeURIComponent(currentKey)}=${encodeURIComponent(currentValueForKey)}`;
}, "");
export const parseQueryParams = (url: string) => {
const queryParams = url.includes("?") ? url.split("?")[1] : url;
if (!queryParams) {
return {};
}
return queryParams.split("&").reduce(
(acc, curr) => {
const [key, value] = curr.split("=");
return { ...acc, [key as string]: value };
},
{} as Record<string, string | undefined>,
);
}; To use the code above simply instantiate a @eldadfux depending on what you envision for this on the react native sdk, I can PR something, just let me know. Hope this helps in some way! |
馃憻 Reproduction steps
Start a new React Native project.
Enable OAuth.
馃憤 Expected behavior
Should have opened a window for selecting an account from the OAuth client like google
馃憥 Actual Behavior
Throwed Error
馃幉 Appwrite version
Different version (specify in environment)
馃捇 Operating system
Windows
馃П Your Environment
I am using Appwrite v:1.0.1.500
React Native 0.70.1
React 18.1.0
馃憖 Have you spent some time to check if this issue has been raised before?
馃彚 Have you read the Code of Conduct?
The text was updated successfully, but these errors were encountered: