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..d458a05 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"; @@ -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) : "" @@ -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) }) @@ -371,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) : "", @@ -417,8 +430,8 @@ const handleDrag = (floatButton, container) => { Step 1: Request for Device Flow Authorization -

Authorization Endpoint

- +

accessToken Endpoint

+

Scope