代码之家  ›  专栏  ›  技术社区  ›  Souvik De

无法使用auth0的access_token获取用户信息

  •  1
  • Souvik De  · 技术社区  · 6 月前

    我正在尝试构建一个简单的身份验证库,我使用axios而不是auth0构建的库。我无法使用访问代码获取用户数据。我也在使用谷歌提供商进行身份验证。

    import axios from 'axios'
    
    export default class Auth {
        constructor(
            private domain: string,
            private client_id: string,
            private redirect_uri: string
        ) {}
    
        startAuthFlow(): string {
            const params = new URLSearchParams({
                response_type: 'code',
                client_id: this.client_id,
                redirect_uri: this.redirect_uri,
                scope: 'offline_access'
            })
            const authURI = `https://${this.domain}/authorize?${params.toString()}`
            return authURI
        }
    
        async handleCallback(code: string) {
            return await this.exchangeCodeForToken(code)
        }
    
        async getUserInfo(accessToken: string) {
            const userInfoEndpoint = `https://${this.domain}/userinfo`
            try {
                const response = await axios.get(userInfoEndpoint, {
                    params: {
                        scope: "openid profile email"
                    },
                    headers: {
                        Authorization: `Bearer ${accessToken}`
                    }
                })
                return response.data
            } catch (error) {
                throw error
            }
        }
    
        async refreshToken(refresh_token: string) {
            const tokenEndpoint = `https://${this.domain}/oauth/token`
            const payload = {
                grant_type: 'refresh_token',
                client_id: this.client_id,
                refresh_token
            }
            try {
                const response = await axios.post(tokenEndpoint, payload, {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })
                return response.data
            } catch (error) {
                throw error
            }
        }
    
        private async exchangeCodeForToken(code: string) {
            const tokenEndPoint = `https://${this.domain}/oauth/token`
            const payload = {
                grant_type: 'authorization_code',
                client_id: this.client_id,
                client_secret: '[my client secret]',
                code,
                redirect_uri: this.redirect_uri,
                scope: 'openid profile email'
            }
            try {
                const reponse = await axios.post(tokenEndPoint, payload)
                const { access_token, id_token, refresh_token } = reponse.data
                return { access_token, id_token, refresh_token }
            } catch (error) {
                throw error
            }
        }
    }
    
    
    

    我正在一个express应用程序中使用这个库来测试它。

    const express = require('express')
    const Auth = require('../auth').default
    const auth = new Auth('[domain].us.auth0.com', '[client ID]', 'http://localhost:3000/callback')
    
    const app = new express()
    
    app.get('/', (req,res) => {
        return res.send('Hello')
    })
    
    app.get('/login', (req, res) => {
        res.redirect(auth.startAuthFlow())
    })
    
    app.get('/callback', async (req, res) => {
        const { code } = req.query
        try {
            const { access_token } = await auth.handleCallback(code)
            console.log(access_token)
            const user = await auth.getUserInfo(access_token)
            console.log("USER: ", user)
    
            res.redirect('/')
        } catch (error) {
            console.log(error)
            return res.status(404).send(error)
        }
    })
    
    app.listen(3000, () => {
        console.log('Server running on port 3000')
    })
    
    

    有人能帮我解释为什么我无法获取用户数据吗?我可以在auth0仪表板中看到用户数据 enter image description here

    1 回复  |  直到 6 月前
        1
  •  1
  •   Bench Vue    6 月前

    你错过了

    两者均已提取 user.name user.email user 对象

    您的程序在登录过程后获取用户信息(包括他们的姓名和电子邮件)的功能是正确的。

    .env

    AUTH0_DOMAIN=[your-domain].us.auth0.com
    AUTH0_CLIENT_ID=[Your CLIENT ID]
    AUTH0_CLIENT_SECRET=[Your CLIENT SECRET]
    AUTH0_REDIRECT_URI=http://localhost:3000/callback
    PORT=3000
    

    tsconfig.json

    {
      "compilerOptions": {
        "target": "es2016",
        "module": "commonjs",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
      }
    }
    

    package.json

    {
      "dependencies": {
        "axios": "^1.7.9",
        "dotenv": "^16.4.7",
        "express": "^4.21.2"
      },
      "devDependencies": {
        "typescript": "^5.7.2"
      }
    }
    

    clinet.ts

    import axios from 'axios'
    
    export default class Auth {
        constructor(
            private domain: string,
            private client_id: string,
            private redirect_uri: string,
            private client_secret: string
        ) {}
    
        startAuthFlow(): string {
            const params = new URLSearchParams({
                response_type: 'code',
                client_id: this.client_id,
                redirect_uri: this.redirect_uri,
                scope: 'openid profile email offline_access'
            });
            const authURI = `https://${this.domain}/authorize?${params.toString()}`;
            return authURI;
        }
    
        async handleCallback(code: string) {
            return await this.exchangeCodeForToken(code);
        }
    
        async getUserInfo(accessToken: string) {
            const userInfoEndpoint = `https://${this.domain}/userinfo`;
            try {
                const response = await axios.get(userInfoEndpoint, {
                    headers: {
                        Authorization: `Bearer ${accessToken}`
                    }
                });
                return response.data;
            } catch (error) {
                throw new Error(`Failed to fetch user info: ${error}`);
            }
        }
    
        async refreshToken(refresh_token: string) {
            const tokenEndpoint = `https://${this.domain}/oauth/token`;
            const payload = {
                grant_type: 'refresh_token',
                client_id: this.client_id,
                refresh_token
            };
            try {
                const response = await axios.post(tokenEndpoint, payload, {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });
                return response.data;
            } catch (error) {
                throw new Error(`Failed to refresh token: ${error}`);
            }
        }
    
        private async exchangeCodeForToken(code: string) {
            const tokenEndPoint = `https://${this.domain}/oauth/token`;
            const payload = {
                grant_type: 'authorization_code',
                client_id: this.client_id,
                client_secret: this.client_secret,
                code,
                redirect_uri: this.redirect_uri
            };
            try {
                const response = await axios.post(tokenEndPoint, payload, {
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });
                const { access_token, id_token, refresh_token } = response.data;
                return { access_token, id_token, refresh_token };
            } catch (error) {
                throw new Error(`Failed to exchange code for token: ${error}`);
            }
        }
    }
    
    

    server.js

    require('dotenv').config();
    const express = require('express');
    const Auth = require('./client').default;
    
    const auth = new Auth(
        process.env.AUTH0_DOMAIN,
        process.env.AUTH0_CLIENT_ID,
        process.env.AUTH0_REDIRECT_URI,
        process.env.AUTH0_CLIENT_SECRET
    );
    
    const app = express();
    
    app.use(express.json());
    
    // CORS Middleware (optional, for frontend integration)
    app.use((req, res, next) => {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        next();
    });
    
    app.get('/', (req, res) => {
        return res.send('Hello, Auth0 Demo!');
    });
    
    app.get('/login', (req, res) => {
        res.redirect(auth.startAuthFlow());
    });
    
    app.get('/callback', async (req, res) => {
        const { code } = req.query;
        try {
            const { access_token } = await auth.handleCallback(code);
            const user = await auth.getUserInfo(access_token);
            console.log('User Info:', user);
    
            // Extract the user's name and email
            const userName = user.name || 'Unknown User';
            const userEmail = user.email || 'No email provided';
    
            // Send the response with user details
            res.send(`
                <h1>Welcome, ${userName}!</h1>
                <p>Email: ${userEmail}</p>
                <p>User information has been logged to the console.</p>
            `);
        } catch (error) {
            console.error(error);
            res.status(500).send('Authentication failed');
        }
    });
    
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
        console.log(`Server running on port ${PORT}`);
    });
    
    

    安装依赖项

    npm install
    

    编译 client.ts

    tsc
    

    快跑 server.js

    node server.js
    

    通过浏览器登录

    http://localhost:3000/login
    

    结果

    enter image description here