這幾天我們都是透過電腦版的Line來做測試,但是如果是使用手機版的話,會發現當我們點擊Google OAuth的URL要進行認證授權的時候,雖然前面的步驟都一切正常,但是最後會出現像下面這樣的錯誤。
這個時候如果我們把網址複製到外面,用手機的Chrome來打開就可以正常的授權登入why?
其實Google OAuth 服務有一個安全政策,限制了在一些特定的瀏覽器或瀏覽器類型中使用 OAuth 進行授權。這裡我們看到的錯誤代碼 403 中的 "disallowed_useragent" ,表示我們使用的是不被 Google 允許的使用者代理 (User Agent)。
透過Line內部打開的瀏覽器,我們稱為In-App browser,也就是說在Line的 In-App browser中,使用了某種特定的 User Agent,而這個 User Agent 又被Google判定為不符合其安全標準,因此導致無法正常授權。
那我們到底是使用什麼User Agent呢? 我們可以透過寫js用navigator.userAgent
來撈,但這邊我們直接用這個網站來查詢,以下是我在不同瀏覽器開啟的結果。
電腦Chrome:
手機Chrome:
Line In-App browser:
現在我們可以看出來,Line In-App browser應該就是因為多了Line的字段,所以不被Google允許直接被403擋下來。
不過還好外部瀏覽器是沒問題的,我們只要繞過In-App browser讓使用者到外部去進行授權就好,而好在Line官方本身就有提供一個功能,只要在網址後面加上?openExternalBrowser=1
,在點擊網址的時候就會跳轉到外部瀏覽器開啟了。
那我們就來改造一下我們的LoginURL,我們的這個service會需要一個function來幫網址加上?openExternalBrowser=1
。首先我們到domain新增drive/login.go,來對service提供功能使用。
// internal\domain\drive\login.go
package drive
import "net/url"
func AppendOpenExternalBrowserParam(originalURL string) (string, error) {
// 將提供的原始URL字串解析成*url.URL
parsedURL, err := url.Parse(originalURL)
if err != nil {
return "", err
}
// 取得URL的查詢參數
query := parsedURL.Query()
// 將 "openExternalBrowser" 參數添加到查詢參數中,值為 "1"
query.Add("openExternalBrowser", "1")
// 將更新後的查詢參數重新設置到parsedURL中
parsedURL.RawQuery = query.Encode()
// 返回修改後的URL
return parsedURL.String(), nil
}
接著回到login_service.go
,我們import剛剛建立的domain drive pkg近來,命名為domainDrive。我們這個service從adapter拿到的oauthURL後丟到domain去取得最終resURL後返回。
// internal\app\service\drive\login_service.go
import (
"context"
"log"
"github.com/onepiece010938/Line2GoogleDriveBot/internal/adapter/dynamodb"
domainDrive "github.com/onepiece010938/Line2GoogleDriveBot/internal/domain/drive"
)
func (dr *GoogleDriveService) LoginURL(ctx context.Context, lineID string) string {
oauthURL := dr.driveServiceGoogleOA.OAuthLoginURL(lineID)
resURL, err := domainDrive.AppendOpenExternalBrowserParam(oauthURL)
if err != nil {
log.Println("Error:", err)
return ""
}
return resURL
}
最後我們回到linebot上測試
可以看到回傳的URL已經有加上對應的參數了,手機版點擊後也能自動跳轉到外部瀏覽器了,那我們今天就寫到這,不知不覺22天了,那我們明天見囉~