feat(Strava Node): Allow custom OAuth2 scopes (#29972)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garrit Franke
2026-05-07 11:57:03 +02:00
committed by GitHub
parent 1cb7c591b3
commit 5abcae686c
3 changed files with 88 additions and 7 deletions
+1
View File
@@ -100,6 +100,7 @@ export const GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE = [
'microsoftOAuth2Api',
'highLevelOAuth2Api',
'mcpOAuth2Api',
'stravaOAuth2Api',
'wordpressOAuth2Api',
];
@@ -1,5 +1,7 @@
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
const defaultScopes = 'activity:read_all,activity:write';
export class StravaOAuth2Api implements ICredentialType {
name = 'stravaOAuth2Api';
@@ -30,19 +32,50 @@ export class StravaOAuth2Api implements ICredentialType {
default: 'https://www.strava.com/oauth/token',
required: true,
},
{
displayName: 'Scope',
name: 'scope',
type: 'hidden',
default: 'activity:read_all,activity:write',
required: true,
},
{
displayName: 'Auth URI Query Parameters',
name: 'authQueryParameters',
type: 'hidden',
default: '',
},
{
displayName: 'Custom Scopes',
name: 'customScopes',
type: 'boolean',
default: false,
description: 'Whether to define custom OAuth2 scopes instead of the defaults',
},
{
displayName:
'The default scopes needed for the node to work are already set. If you change these the node may not function correctly.',
name: 'customScopesNotice',
type: 'notice',
default: '',
displayOptions: {
show: {
customScopes: [true],
},
},
},
{
displayName: 'Enabled Scopes',
name: 'enabledScopes',
type: 'string',
displayOptions: {
show: {
customScopes: [true],
},
},
default: defaultScopes,
description: 'Comma-separated list of Strava OAuth2 scopes to request',
},
{
displayName: 'Scope',
name: 'scope',
type: 'hidden',
default: `={{$self["customScopes"] ? $self["enabledScopes"] : "${defaultScopes}"}}`,
required: true,
},
{
displayName: 'Authentication',
name: 'authentication',
@@ -0,0 +1,47 @@
import { StravaOAuth2Api } from '../StravaOAuth2Api.credentials';
describe('StravaOAuth2Api Credential', () => {
const credential = new StravaOAuth2Api();
const defaultScopes = 'activity:read_all,activity:write';
it('should have correct credential metadata', () => {
expect(credential.name).toBe('stravaOAuth2Api');
expect(credential.extends).toEqual(['oAuth2Api']);
const authUrlProperty = credential.properties.find((p) => p.name === 'authUrl');
expect(authUrlProperty?.default).toBe('https://www.strava.com/oauth/authorize');
const accessTokenUrlProperty = credential.properties.find((p) => p.name === 'accessTokenUrl');
expect(accessTokenUrlProperty?.default).toBe('https://www.strava.com/oauth/token');
});
it('should use body authentication', () => {
const authenticationProperty = credential.properties.find((p) => p.name === 'authentication');
expect(authenticationProperty?.type).toBe('hidden');
expect(authenticationProperty?.default).toBe('body');
});
it('should have custom scopes toggle defaulting to false', () => {
const customScopesProperty = credential.properties.find((p) => p.name === 'customScopes');
expect(customScopesProperty?.type).toBe('boolean');
expect(customScopesProperty?.default).toBe(false);
});
it('should have enabledScopes defaulting to the current default scope list', () => {
const enabledScopesProperty = credential.properties.find((p) => p.name === 'enabledScopes');
expect(enabledScopesProperty?.default).toBe(defaultScopes);
});
it('should only show enabledScopes when customScopes is true', () => {
const enabledScopesProperty = credential.properties.find((p) => p.name === 'enabledScopes');
expect(enabledScopesProperty?.displayOptions?.show?.customScopes).toEqual([true]);
});
it('should use enabledScopes when customScopes is true, otherwise fall back to defaults', () => {
const scopeProperty = credential.properties.find((p) => p.name === 'scope');
expect(scopeProperty?.type).toBe('hidden');
expect(scopeProperty?.default).toBe(
`={{$self["customScopes"] ? $self["enabledScopes"] : "${defaultScopes}"}}`,
);
});
});