You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Passport-OnShape OAuth授权流程认证后报400无效请求故障

OnShape OAuth认证返回400「Invalid request」问题

我正在开发一款对接OnShape API的应用,采用OAuth认证方式。不管是自行编写的代码还是官方提供的示例,都遇到了相同问题:跳转至OnShape登录页的流程正常,但完成登录后会返回400「Invalid request」错误。之前已经成功为Google账号实现OAuth并调用其API,不确定该问题是OnShape特有、对OAuth的理解偏差还是流程配置问题。

错误响应信息

{
  "message": "Invalid request.",
  "status": 400,
  "code": 0,
  "moreInfoUrl": ""
}

相关截图

  • 浏览器端OnShape OAuth登录页
  • OnShape OAuth授权确认页
  • 400错误页面

授权请求URL

https://oauth.onshape.com/oauth/authorize?response_type=code&redirect_uri=https:%2F%2Flocalhost:443%2Fauth%2Fonshape%2Fcallback&scope=OAuth2ReadPII&client_id=REDACTED

官方参考

官方示例基于Express和Passport,文档包含OAuth认证流程说明。

前提假设

  • Client ID和Client Secret配置正确
  • 回调URL已在OnShape应用中注册(尝试过本地HTTP和Nginx HTTPS两种回调地址,问题均存在)

环境变量配置

ONSHAPE_CALLBACK_URL=http://localhost:5001/auth/onshape/callback
ONSHAPE_CALLBACK_URL_NGINX=https://localhost:443/auth/onshape/callback
ONSHAPE_AUTHORIZATION_URL=https://oauth.onshape.com/oauth/authorize
ONSHAPE_TOKEN_URL=https://oauth.onshape.com/oauth/token
ONSHAPE_USER_PROFILE_URL=https://cad.onshape.com/api/users/sessioninfo

代码实现

基础路由(index.js)

app.use('/auth', authRoutes); // 使用routes/auth.js中定义的认证路由

app.get('/', (req, res) => {
    res.send('<h1>Welcome to the OnShape Data Processing Service API</h1><br><a href="/auth/onshape">Authenticate with OnShape</a>');
});

Passport策略配置(config/auth.js)

const { application } = require('express');
const passport = require('passport');
const OnShapeStrategy = require('passport-onshape');
require('dotenv').config();

console.log('OnShape Client ID:', process.env.ONSHAPE_CLIENT_ID);
console.log('OnShape Client Secret:', process.env.ONSHAPE_CLIENT_SECRET ? '[HIDDEN]' : 'Not Set');
console.log('OnShape Callback URL:', process.env.ONSHAPE_CALLBACK_URL);
console.log('OnShape Authorization URL:', process.env.ONSHAPE_AUTHORIZATION_URL);
console.log('OnShape Token URL:', process.env.ONSHAPE_TOKEN_URL);
console.log('OnShape User Profile URL:', process.env.ONSHAPE_USER_PROFILE_URL);

// 配置Passport使用OnShape策略进行认证
passport.use(
    new OnShapeStrategy(
        {
            clientID: process.env.ONSHAPE_CLIENT_ID, // OnShape应用注册的Client ID
            clientSecret: process.env.ONSHAPE_CLIENT_SECRET, // OnShape应用注册的Client Secret
            callbackURL: process.env.ONSHAPE_CALLBACK_URL_NGINX, // OnShape认证后重定向的URL,必须和OnShape应用中注册的回调URL一致
            authorizationURL: process.env.ONSHAPE_AUTHORIZATION_URL, // OnShape授权端点
            tokenURL: process.env.ONSHAPE_TOKEN_URL, // OnShape令牌端点
            userProfileURL: process.env.ONSHAPE_USER_PROFILE_URL // OnShape用户信息端点
        },
    // 认证成功后调用此函数,将访问令牌和刷新令牌关联到用户信息供后续使用
    (accessToken, refreshToken, profile, done)=>{
        profile.accessToken = accessToken;
        profile.refreshToken = refreshToken;
        return done(null, profile);
    })
);

// 定义会话管理中用户信息的序列化和反序列化方式
passport.serializeUser((user, done) => {
    done(null, user);
});
passport.deserializeUser((user, done) => {
    done(null, user);
});

module.exports = {
    passport
}

认证路由(routes/auth.js)

const express = require('express');
const router = express.Router();
const { passport } = require('../config/auth.js');
const uuid = require('uuid');
require('dotenv').config();

router.get('/onshape', passport.authenticate(
    'onshape',
    {
        // state: uuid.v4(), // 生成随机state参数用于CSRF保护;生产环境中应存储在会话中并在回调时验证
        scope: 'OAuth2ReadPII',
    }
));

router.get('/debug-auth', (req, res) => {
  const params = new URLSearchParams({
    response_type: 'code',
    client_id: process.env.ONSHAPE_CLIENT_ID,
    redirect_uri: process.env.ONSHAPE_CALLBACK_URL,
    scope: 'OAuth2ReadPII,OAuth2Read',
    state: 'test123',
  });

  const url =
    `https://oauth.onshape.com/oauth/authorize?${params.toString()}`;

  console.log(url);

  res.redirect(url);
});

router.get('/onshape/callback', passport.authenticate('onshape', { failureRedirect: '/auth/failure' }), (req, res) => {
    res.redirect('/protected');
});

router.get('/onshape/logout', (req, res, next) => {

});

router.get('/auth/failure', (req, res) => {
    res.send('<>h1>Authentication Failed</h1><br><a href="/auth/onshape">Try Again</a><br><a href="/">Go Back to Home</a>');
});

module.exports = router;

这是我第一次接触OAuth,目前尚未找到解决方案,如需其他信息请告知。

内容的提问来源于stack exchange,提问作者mag06998

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 01:47:27