OAuth登入實作

  • 990
  • 0

串接OAuth登入流程

 

綜觀流程:

1. 登入按鈕按下去後導至第三方頁面登入並且把資料待在URL上面

2. 第三方驗證獲取資料 

3. 導回指定頁面並且把資料帶在URL上面

 

 

設定檔案

const config = {
  // 请求授权地址
  userAuthorizationUri: `${process.env.VUE_APP_OAUTH_BASEURI}/connect/authorize`,
  // accessToken请求地址
  accessTokenUri: `${process.env.VUE_APP_OAUTH_BASEURI}/connect/token`,
  // 用户信息请求地址
  userInfoUri: `${process.env.VUE_APP_OAUTH_BASEURI}/connect/userinfo`,
  // 登出请求地址
  logoutUri: `${process.env.VUE_APP_OAUTH_BASEURI}/connect/endsession`,
  // 项目地址
  localuri: process.env.VUE_APP_OAUTH_LOCALURI,
  // 回调地址
  redirect_uri: `${process.env.VUE_APP_OAUTH_LOCALURI}/oauthloading`,
  // 案例资源服务器地址
  resUri: '',
  // 客户端相关标识,请从认证服务器申请
  client_id: process.env.VUE_APP_OAUTH_CLIENT_ID,
  client_secret: '',
  // 申请的权限范围
  // scope: 'offline_access+openid+profile+PlmAPI+role+email+phone',
  scope: 'openid+profile+PlmAPI+email',
  // scope: '',
  // 可选参数,客户端的当前状态,可以指定任意值,用于校验,此次案例不做相关认证
  state: '',
  // 一些固定的请求参数
  response_type: 'code',
  grant_type: 'authorization_code',
  code: ''
}
// response_type:表示授权类型,必选项,此处的值固定为"code"
// client_id:表示客户端的ID,必选项
// redirect_uri:表示重定向URI,可选项
// scope:表示申请的权限范围,可选项
// state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
export default config

使用策略模式來管理登入

import { delCookie, getCookie } from './cookie.js'
import { encode } from 'js-base64'
export const strategies = {
  defaultLogIn  (token, ecode) { //普通的登入
    window.document.cookie = `token=${token}; path=/`
    ecode = encode(ecode)
    window.document.cookie = `ecode=${ecode}; path=/`
    return { can: true, uri: '' }
  },
  uriLogIn (token, ecode) { //信箱連結需要用到的登入
    const urlParams = new URLSearchParams(window.location.search)
    const urlParamsFormat = new URLSearchParams(urlParams.get('state'))
    const uri = window.decodeURI(window.decodeURIComponent(urlParamsFormat.get('uri')) + `&ecode=${encode(ecode)}`)
    window.location.href = uri
    return { can: false, uri: '' }
  },
  PCASignLogIn (token, ecode) {
    window.document.cookie = `token=${token}; path=/`
    ecode = encode(ecode)
    window.document.cookie = `ecode=${ecode}; path=/`
    const urlParams = new URLSearchParams(window.location.search)
    const urlParamsFormat = new URLSearchParams(urlParams.get('state'))
    const id = window.decodeURI(window.decodeURIComponent(urlParamsFormat.get('Sign')))
    return { can: true, uri: `/PLM/PCA/${id}` }
  }
}
export const oauth = {
  canLogin (grantedPolicies) {
    return Object.keys(grantedPolicies).some(str => str.includes('MenuManagement'))
  },
  oauthLogin (grantedPolicies, token, email) {
    const strategy = this.loginController()
    if (strategy === 'defaultLogIn') {
      if (this.canLogin(grantedPolicies)) {
        return strategies[strategy](token, email)
      }
    } else {
      return strategies[strategy](token, email)
    }
  },
  loginController () {
    if (window.location.search.includes('uri')) {
      return 'uriLogIn'
    }
    if (window.location.search.includes('Sign')) {
      return 'PCASignLogIn'
    }
    return 'defaultLogIn'
  },
  loadEcode () {
    return getCookie('ecode') ? getCookie('ecode') : false
  },
  loggedIn () {
    return !!(getCookie('ecode') && getCookie('token'))
  },
  logOut (Vue) {
    delCookie('ecode')
    delCookie('token')
    delCookie('empNo')
    delCookie('userName')
    delCookie('originEmpNo')
    delCookie('originUserName')
    Vue.$router.push('/')
  }
}

參考資料:

https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E8%AA%8D%E8%AD%98-oauth-2-0-%E4%B8%80%E6%AC%A1%E4%BA%86%E8%A7%A3%E5%90%84%E8%A7%92%E8%89%B2-%E5%90%84%E9%A1%9E%E5%9E%8B%E6%B5%81%E7%A8%8B%E7%9A%84%E5%B7%AE%E7%95%B0-c42da83a6015