Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## 29.1.0

* Added: optional `state` parameter on `createOAuth2Token`, returned unchanged on the success and failure URLs

## 29.0.0

* Stable release of the dedicated database APIs: `mysql`, `postgresql`, `mongo`, `documentsDB`, and `vectorsDB` services, previously released as release candidates
Expand Down
1 change: 1 addition & 0 deletions docs/examples/account/create-o-auth-2-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ const result = await account.createOAuth2Token({
success: 'https://example.com', // optional
failure: 'https://example.com', // optional
scopes: [], // optional
state: '<STATE>', // optional
});
```
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "node-appwrite",
"homepage": "https://appwrite.io/support",
"description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
"version": "29.0.0",
"version": "29.1.0",
"license": "BSD-3-Clause",
"main": "dist/index.js",
"type": "commonjs",
Expand Down
4 changes: 2 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class AppwriteException extends Error {
}

function getUserAgent() {
let ua = 'AppwriteNodeJSSDK/29.0.0';
let ua = 'AppwriteNodeJSSDK/29.1.0';

// `process` is a global in Node.js, but not fully available in all runtimes.
const platform: string[] = [];
Expand Down Expand Up @@ -142,7 +142,7 @@ class Client {
'x-sdk-name': 'Node.js',
'x-sdk-platform': 'server',
'x-sdk-language': 'nodejs',
'x-sdk-version': '29.0.0',
'x-sdk-version': '29.1.0',
'user-agent': getUserAgent(),
'X-Appwrite-Response-Format': '2.0.0',
};
Expand Down
17 changes: 15 additions & 2 deletions src/services/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2905,6 +2905,7 @@ export class Account {
* @param {string} params.success - URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.
* @param {string} params.failure - URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.
* @param {string[]} params.scopes - A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.
* @param {string} params.state - An opaque value your app generates and keeps, for example in a cookie. It is returned unchanged as the `state` query parameter on the success and failure URLs, so your app can check that the sign-in it receives is one it started. Printable ASCII only (RFC 6749 Appendix A.5). Max length: 256 chars.
* @throws {AppwriteException}
* @returns {Promise<string>}
*/
Expand All @@ -2913,6 +2914,7 @@ export class Account {
success?: string;
failure?: string;
scopes?: string[];
state?: string;
}): Promise<string>;
/**
* Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed.
Expand All @@ -2925,6 +2927,7 @@ export class Account {
* @param {string} success - URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.
* @param {string} failure - URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.
* @param {string[]} scopes - A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.
* @param {string} state - An opaque value your app generates and keeps, for example in a cookie. It is returned unchanged as the `state` query parameter on the success and failure URLs, so your app can check that the sign-in it receives is one it started. Printable ASCII only (RFC 6749 Appendix A.5). Max length: 256 chars.
* @throws {AppwriteException}
* @returns {Promise<string>}
* @deprecated Use the object parameter style method for a better developer experience.
Expand All @@ -2934,6 +2937,7 @@ export class Account {
success?: string,
failure?: string,
scopes?: string[],
state?: string,
): Promise<string>;
createOAuth2Token(
paramsOrFirst:
Expand All @@ -2942,15 +2946,17 @@ export class Account {
success?: string;
failure?: string;
scopes?: string[];
state?: string;
}
| OAuthProvider,
...rest: [string?, string?, string[]?]
...rest: [string?, string?, string[]?, string?]
): Promise<string> {
let params: {
provider: OAuthProvider;
success?: string;
failure?: string;
scopes?: string[];
state?: string;
};

if (
Expand All @@ -2960,27 +2966,31 @@ export class Account {
('provider' in paramsOrFirst ||
'success' in paramsOrFirst ||
'failure' in paramsOrFirst ||
'scopes' in paramsOrFirst)
'scopes' in paramsOrFirst ||
'state' in paramsOrFirst)
) {
params = (paramsOrFirst || {}) as {
provider: OAuthProvider;
success?: string;
failure?: string;
scopes?: string[];
state?: string;
};
} else {
params = {
provider: paramsOrFirst as OAuthProvider,
success: rest[0] as string,
failure: rest[1] as string,
scopes: rest[2] as string[],
state: rest[3] as string,
};
}

const provider = params.provider;
const success = params.success;
const failure = params.failure;
const scopes = params.scopes;
const state = params.state;
if (typeof provider === 'undefined') {
throw new AppwriteException(
'Missing required parameter: "provider"',
Expand All @@ -3000,6 +3010,9 @@ export class Account {
if (typeof scopes !== 'undefined') {
apiPayload['scopes'] = scopes;
}
if (typeof state !== 'undefined') {
apiPayload['state'] = state;
}
Comment on lines +3013 to +3015

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add regression coverage for OAuth2 state forwarding

The existing createOAuth2Token test in test/services/account.test.js:1130 calls only the provider argument and returns a fixed redirect, so it would still pass if state were dropped. Please cover both calling styles, verifying the outgoing URL's decoded state (including query-special characters) and omission when state is undefined.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/account.ts
Line: 3013-3015

Comment:
**Add regression coverage for OAuth2 state forwarding**

The existing `createOAuth2Token` test in `test/services/account.test.js:1130` calls only the provider argument and returns a fixed redirect, so it would still pass if state were dropped. Please cover both calling styles, verifying the outgoing URL's decoded state (including query-special characters) and omission when state is undefined.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟡 Minor · testing · Reply if this doesn't apply.

const uri = new URL(this.client.config.endpoint + apiPath);

const apiHeaders: { [header: string]: string } = {
Expand Down
Loading