Fxiaoke · Authentication Profile
Fxiaoke Authentication
Authentication
Fxiaoke secures its APIs with oauth2 and custom-token across 4 declared security schemes, as derived from its OpenAPI definitions. OAuth 2.0 is offered via the clientCredentials and authorizationCode flow(s).
CompanyEnterpriseCRMSalesMarketingCustomer ServiceSaaSChinaPaaS
Methods: oauth2, custom-token
Schemes: 4
OAuth flows: clientCredentials, authorizationCode
API key in: header, body
Security Schemes
enterprise-app-token oauth2
authorization-code oauth2
oauth2.1-pkce oauth2
jsapi-ticket-signature custom-signature
Source
Authentication Profile
generated: '2026-08-13'
method: searched
source: https://developer.fxiaoke.com/openapi_v2/start/auth/app-info.html
docs:
- https://developer.fxiaoke.com/openapi_v2/start/auth/app-info.html
- https://developer.fxiaoke.com/openapi_v2/start/auth/auth-code.html
- https://developer.fxiaoke.com/openapi_v2/start/auth/refresh.html
- https://developer.fxiaoke.com/openapi_v2/start/example/public.html
- https://developer.fxiaoke.com/openapi_v2/start/example/old.html
- https://open.fxiaoke.com/.well-known/oauth-authorization-server
summary:
types: [oauth2, custom-token]
api_key_in: [header, body]
oauth2_flows: [clientCredentials, authorizationCode]
base_host: https://open.fxiaoke.com
surfaces: 2
note: >-
Fxiaoke runs TWO distinct OAuth surfaces that do not share endpoints or parameter
names — the documented developer flow under /oauth2.0/{authorize,token}, and an
undocumented RFC 8414-conformant PKCE server whose metadata advertises
/oauth2.0/cli/authorize and /oauth2.0/pkce/token. Only the first is described in the
developer manual.
schemes:
- name: enterprise-app-token
type: oauth2
flow: clientCredentials
documented: true
description: >-
客户端凭证模式. A tenant creates a self-built app in the Fxiaoke admin console with
developer mode enabled and receives appId, appSecret and permanentCode. These are
exchanged for a short-lived corpAccessToken that authenticates all subsequent Open
API v2 calls. The mode supports acting as any employee by supplying their ID.
token_endpoint: https://open.fxiaoke.com/oauth2.0/token
token_endpoint_legacy: https://open.fxiaoke.com/cgi/corpAccessToken/get/V2
token_query_params:
- thirdTraceId # caller-supplied UUIDv4, required, must be unique per request
request:
content_type: application/json
method: POST
headers: none — the token call is the one endpoint that sends no auth headers
fields:
- {name: appId, required: true}
- {name: appSecret, required: true}
- {name: permanentCode, required: true}
- {name: grantType, required: true, value: app_secret}
response_fields:
- accessToken
- expiresIn
- openUserId # carries the enterprise openCorpId in this flow
- appId
- ea # enterprise account, becomes the x-fs-ea header
- errorCode
- errorMessage
- traceId
token_lifetime_seconds: 7200
caching_guidance: >-
Calling within the first 6600s returns the SAME token; calling between 6600s and
7200s issues a NEW token while the old one stays valid until 7200s. The documented
contract is therefore: cache for 6600s, refresh in the 6600–7200s window, and key
retry logic off errorCode 20016.
endpoint_limits:
rate: 10 calls per minute
concurrency: not permitted (不能并发调用本接口)
ref: rate-limits/fxiaoke-rate-limits.yml
- name: authorization-code
type: oauth2
flow: authorizationCode
documented: true
description: >-
授权码模式, for web applications with a backend that need to act as an end user. The
user is redirected to Fxiaoke, authorizes, and the app exchanges the returned code
for an access token plus a refresh token.
authorization_endpoint: https://open.fxiaoke.com/oauth2.0/authorize
token_endpoint: https://open.fxiaoke.com/oauth2.0/token
authorize_params:
- {name: appId, required: true, standard_name: client_id}
- {name: redirectUrl, required: true, standard_name: redirect_uri}
- {name: responseType, required: true, value: code, standard_name: response_type}
- {name: state, required: true}
- {name: thirdTraceId, required: true, standard_name: null}
token_params:
- {name: appId, required: true}
- {name: appSecret, required: true}
- {name: redirectUrl, required: true}
- {name: code, required: true}
- {name: grantType, required: true, value: authorization_code}
response_fields: [openUserId, accessToken, corpId, expiresIn, refreshToken, errorCode, errorMessage]
access_token_lifetime_seconds: 7200
refresh_token_lifetime: 2 months
pkce: false
csrf: >-
state is mandatory and the docs require the app to verify it on callback, with a
recommended construction of MD5(timestamp + account).
redirect_uri_binding: >-
The redirectUrl domain must match the login-authorization domain registered on the
app detail page.
spec_deviation: >-
Parameter names are camelCase Fxiaoke names, not RFC 6749 names — appId not
client_id, redirectUrl not redirect_uri, responseType not response_type, grantType
not grant_type. A standards-compliant OAuth client library cannot drive this flow
without custom parameter mapping. The token exchange also sends appSecret in a JSON
body rather than using a documented client authentication method.
- name: oauth2.1-pkce
type: oauth2
flow: authorizationCode
documented: false
description: >-
An RFC 8414-conformant authorization server advertised at
https://open.fxiaoke.com/.well-known/oauth-authorization-server but absent from the
developer manual. Public clients (token_endpoint_auth_methods_supported ["none"])
use PKCE S256 with authorization_code and refresh_token grants and may self-register
through the RFC 7591 dynamic client registration endpoint. The "cli" and "pkce" path
segments and the anonymous-client posture are the shape a CLI or agent client
expects.
issuer: https://open.fxiaoke.com/oauth2.0
authorization_endpoint: https://open.fxiaoke.com/oauth2.0/cli/authorize
token_endpoint: https://open.fxiaoke.com/oauth2.0/pkce/token
registration_endpoint: https://open.fxiaoke.com/oauth2.0/register
jwks_uri: https://open.fxiaoke.com/oauth2.0/jwks
grant_types: [authorization_code, refresh_token]
response_types: [code]
code_challenge_methods: [S256]
token_endpoint_auth_methods: [none]
subject_types: [public]
id_token_signing_alg: [RS256]
scopes_supported: null
caveats:
- >-
jwks_uri returns an empty key set ({"keys":[]}) as of 2026-08-13, so an RS256
id_token cannot be verified by any client following discovery.
- >-
No matching RFC 9728 oauth-protected-resource metadata is served — the path returns
the gateway's errorCode 10006 envelope — so there is no advertised resource server
for these tokens.
- No scopes_supported is advertised and no scope registry is published anywhere.
probed: '2026-08-13'
evidence: well-known/fxiaoke-oauth-authorization-server.json
- name: jsapi-ticket-signature
type: custom-signature
documented: true
description: >-
Client-side JS API calls are authorized by a sha1 signature rather than a bearer
token. A jsapi_ticket (7200s lifetime) is fetched server-side with the
corpAccessToken, then signed together with a nonce, timestamp and the page URL.
ticket_endpoint: https://open.fxiaoke.com/cgi/jsApiTicket/get
ticket_request_fields: [corpAccessToken, corpId]
ticket_response_fields: [ticket, expiresIn, errorCode, errorMessage]
signature_algorithm: >-
sha1 of the ASCII-sorted key=value string built from noncestr, jsapi_ticket,
timestamp and url (fragment removed); result uppercased hex.
ref: components/fxiaoke-components.yml
token_transport:
current:
style: header
headers:
- {name: authorization, value: 'Bearer <token>'}
- {name: x-fs-ea, value: enterprise account from the token response}
- {name: x-fs-userid, value: acting employee CRM ID}
source: https://developer.fxiaoke.com/openapi_v2/start/example/public.html
legacy:
style: body
fields: [corpAccessToken, currentOpenUserId, corpId]
source: https://developer.fxiaoke.com/openapi_v2/start/example/old.html
note: Still documented and functional; no sunset date published.
multi_tenancy:
tenant_identifier: corpId (FSCID_*) / ea
actor_identifier: openUserId, or x-fs-userid under the current convention
app_identifier: appId (FSAID_*)
authorization_model: >-
Per-app, per-enterprise grants administered by the tenant. Denials surface as
errorCode 15003, 20014, 20020, 20021, 20022 and 20023 rather than HTTP 403.
scopes:
published: false
note: >-
A scope parameter exists (errorCodes 10006 and 11006 reference it) but no scope
values, permission catalog or consent screen inventory is published, and the RFC
8414 metadata omits scopes_supported. See scopes/fxiaoke-scopes.yml.
notes: >-
No OpenAPI/Swagger definition is published, so this profile was captured from the
developer documentation and live RFC 8414 metadata rather than derived from a spec.
The strongest auth signal is clarity: two documented grant types with complete
parameter tables, explicit token lifetimes and explicit caching guidance. The
weaknesses are non-standard parameter naming, an empty JWKS, no scope registry, and
the fact that every auth failure arrives as HTTP 200 with a non-zero errorCode.