From aa8af8289d89d0a8f643674a42ea85f8fdbe667e Mon Sep 17 00:00:00 2001 From: Laceyoo <51255903050@stu.ecnu.edu.cn> Date: Fri, 22 Dec 2023 16:28:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=B0=86=E5=89=8D=E7=AB=AF=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=8F=91=E9=80=81axios=E8=AF=B7=E6=B1=82=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E9=80=9A=E8=BF=87=E5=90=8E=E7=AB=AF=E8=BD=AC=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/oauth2_device_flow.go | 23 +++++++++++ controller/route.go | 1 + front-standalone/src/api/playground.ts | 6 +++ .../views/playground/components/Device.vue | 41 ++++++++++++------- 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/controller/oauth2_device_flow.go b/controller/oauth2_device_flow.go index 7909e4e..c3fdf99 100644 --- a/controller/oauth2_device_flow.go +++ b/controller/oauth2_device_flow.go @@ -17,6 +17,29 @@ type ReqDeviceData struct { ExpiresIn int `json:"expires_in"` } +type ReqUserCodeData struct { + InitialAddress string `json:"initialAddress"` +} + +func getUserCode(c *gin.Context) { + reqData := ReqUserCodeData{} + if err := c.Bind(&reqData); err != nil { + c.JSON(http.StatusOK, handleError(err.Error())) + return + } + method := "POST" + apiAddr := reqData.InitialAddress + body := fmt.Sprintf("") + header := make(map[string]string) + + res, err := models.HandleRequest(method, apiAddr, g.UserAgent, body, g.Config().Timeout, header) + if err != nil { + c.JSON(http.StatusOK, handleError(err.Error())) + return + } + c.JSON(http.StatusOK, handleSuccess(res)) +} + func deviceFlow(c *gin.Context) { reqData := ReqDeviceData{} if err := c.Bind(&reqData); err != nil { diff --git a/controller/route.go b/controller/route.go index e201531..3eb331a 100644 --- a/controller/route.go +++ b/controller/route.go @@ -21,6 +21,7 @@ func Routes(r *gin.Engine) { playground.Use(NoCache()) playground.POST("/oauth2/pkce", pkce) playground.POST("/oauth2/device_flow", deviceFlow) + playground.POST("/oauth2/user_code", getUserCode) playground.POST("/oauth2/client_credentials", clientCredentials) playground.POST("/oauth2/password", passwordMode) playground.POST("/oauth2/authorization_code", exchangeTokenByCode) diff --git a/front-standalone/src/api/playground.ts b/front-standalone/src/api/playground.ts index 667af67..01429a0 100644 --- a/front-standalone/src/api/playground.ts +++ b/front-standalone/src/api/playground.ts @@ -41,6 +41,12 @@ export const fetchACTokenByPassword = (data) => { }; /** Device Flow */ +/** Step 1 */ +/** Get user_code */ +export const fetchUserCode = (data) => { + return http.post("/oauth2/user_code", data); +} + /** Step 2 */ /** Get access_token with device_code */ export const fetchACTokenByDevice = (data) => { diff --git a/front-standalone/src/views/playground/components/Device.vue b/front-standalone/src/views/playground/components/Device.vue index 1ff3d02..3a5b67a 100644 --- a/front-standalone/src/views/playground/components/Device.vue +++ b/front-standalone/src/views/playground/components/Device.vue @@ -3,7 +3,7 @@ import { onMounted, reactive, ref, watch } from 'vue' import {ElMessage, FormInstance} from 'element-plus' import { LocalStorageService } from "/@/utils/persistence" import useClipboard from 'vue-clipboard3'; -import { fetchACTokenByDevice, fetchApiData, fetchRefreshToken} from "/@/api/playground"; +import {fetchACTokenByDevice, fetchApiData, fetchRefreshToken, fetchUserCode} from "/@/api/playground"; import * as QRCode from 'qrcode' import axios from "axios"; @@ -118,19 +118,32 @@ function handleDeviceFlow() { lss.addItem(cs); } // window.location.href = initialAddress.value; - axios.post(initialAddress.value).then((res) => { - user_code.value = res.data.user_code - verification_uri.value = res.data.verification_uri - device_code.value = res.data.device_code - expires_in.value = res.data.expires_in - // 检查是否获取到user_code,若长度不为0,则跳到Step 2 - if (device_code.value.length === 0 || user_code.value.length === 0 || verification_uri.value.length === 0) { - ElMessage.error("Authorization failed. Check your configurations."); - return; + const dataObject = { + initialAddress: initialAddress.value + }; + fetchUserCode(dataObject).then(({code, msg, data}) => { + if (code === 0) { + const {request, response, rawjson, example} = data; + if (rawjson.user_code === undefined || rawjson.user_code === '') + return + // const {interval, verification_uri, user_code, expires_in, device_code} = rawjson || {}; + if (user_code !== undefined && user_code !== null) { + user_code.value = rawjson.user_code + verification_uri.value = rawjson.verification_uri + device_code.value = rawjson.device_code + expires_in.value = rawjson.expires_in + // 检查是否获取到user_code,若长度不为0,则跳到Step 2 + if (device_code.value.length === 0 || user_code.value.length === 0 || verification_uri.value.length === 0) { + ElMessage.error("Authorization failed. Check your configurations."); + return; + } + activeName.value = '2'; + // 轮询是否获取到token + tokenAvailablelong(expires_in.value); + } + } else { + ElMessage.error("Get user_code failed. Please check your configuration!") } - activeName.value = '2'; - // 轮询是否获取到token - tokenAvailablelong(expires_in.value); }).catch((err) => { console.error('get user code failed: ', err) }) @@ -417,7 +430,7 @@ const handleDrag = (floatButton, container) => { Step 1: Request for Device Flow Authorization -

Authorization Endpoint

+

accessToken Endpoint

From c843eed33f1d6d6f5f944f1783322544b6e6042c Mon Sep 17 00:00:00 2001 From: Laceyoo <51255903050@stu.ecnu.edu.cn> Date: Tue, 26 Dec 2023 21:22:20 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:device=E6=A8=A1=E5=BC=8F=E5=B0=86Step1?= =?UTF-8?q?=E4=B8=AD=E7=9A=84authorization=5Fendpoint=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BAaccessToken=5Fendpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/playground/components/Device.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/front-standalone/src/views/playground/components/Device.vue b/front-standalone/src/views/playground/components/Device.vue index 3a5b67a..d458a05 100644 --- a/front-standalone/src/views/playground/components/Device.vue +++ b/front-standalone/src/views/playground/components/Device.vue @@ -83,7 +83,7 @@ function updateReqAndRes() { // Step 1 const activeName = ref('1'); const s1Data = reactive({ - authorization_endpoint: "", + token_endpoint: "", // redirect_uri: window.location.href.split("?")[0], scope: "", response_type: "device_code", @@ -94,7 +94,7 @@ const initialAddress = ref(""); // 修改的同时拼接成url显示在Grant Url中 function handleS1Change() { - initialAddress.value = s1Data.authorization_endpoint.concat( + initialAddress.value = s1Data.token_endpoint.concat( "?response_type=device_code", s1Data.scope?.length > 0 ? "&scope=".concat(s1Data.scope) : "", props.cfgData.client_id?.length > 0 ? "&client_id=".concat(props.cfgData.client_id) : "" @@ -384,9 +384,9 @@ async function generateQRCode(url) { } watch(props.cfgData, (newValue) => { - s1Data.authorization_endpoint = newValue.authorization_endpoint; + s1Data.token_endpoint = newValue.token_endpoint; s1Data.scope = newValue.default_scope; - initialAddress.value = newValue.authorization_endpoint.concat( + initialAddress.value = newValue.token_endpoint.concat( "?response_type=device_code", newValue.default_scope?.length > 0 ? "&scope=".concat(newValue.default_scope) : "", newValue.client_id?.length > 0 ? "&client_id=".concat(newValue.client_id) : "", @@ -431,7 +431,7 @@ const handleDrag = (floatButton, container) => {

accessToken Endpoint

- +

Scope