drnysdnnb2909701 2017-04-20 09:06
浏览 116
已采纳

如何使用oauth2在Go中实现隐式授予

go version go1.7.4 linux/amd64

I am trying get amazon alexa login using oauth2

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "html/template"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"

    "golang.org/x/oauth2"
    "gopkg.in/oauth2.v3/errors"
    "gopkg.in/oauth2.v3/manage"
    "gopkg.in/oauth2.v3/models"
    "gopkg.in/oauth2.v3/server"
    "gopkg.in/oauth2.v3/store"
    "gopkg.in/session.v1"
)

var (
    config = oauth2.Config{
        ClientID:     "222222",
        ClientSecret: "22222222",
        Scopes:       []string{"all"},
        RedirectURL:  "https://pitangui.amazon.com/spa/skill/account-linking-status.html?vendorId=xxxxxxxxxxxx",
        Endpoint: oauth2.Endpoint{
            AuthURL:  "/authorize",
            TokenURL: "/token",
        },
    }
    globalSessions *session.Manager
)

func init() {
    globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":3600}`)
    go globalSessions.GC()
}

func mainHandler(w http.ResponseWriter, r *http.Request) {

    w.Write([]byte("hello world"))
    fmt.Println("loginHandler")
}

/*
Function Name : main()

Function Description :    This function is capable of running this application and listen for requests comming in

*/
func main() {
    http.HandleFunc("/home", mainHandler)

    // Listen to port 8080 and handle requests

    //------------------------------client.go--------------------------------------------//
    http.HandleFunc("/client", func(w http.ResponseWriter, r *http.Request) {
        log.Println("client")
        u := config.AuthCodeURL("xyz")
        http.Redirect(w, r, u, http.StatusFound)
    })
    http.HandleFunc("/oauth2", func(w http.ResponseWriter, r *http.Request) {
        log.Println("oauth2")
        log.Println("request url is", r.RequestURI)
        log.Println("request method", r.Method)
        requestbody, _ := ioutil.ReadAll(r.Body)
        log.Println("request body is", string(requestbody))
        log.Println("request body is", requestbody)
        r.ParseForm()
        state := r.Form.Get("state")
        if state != "xyz" {
            http.Error(w, "State invalid", http.StatusBadRequest)
            return
        }
        code := r.Form.Get("code")
        log.Println("code is", code)
        if code == "" {
            http.Error(w, "Code not found", http.StatusBadRequest)
            return
        }
        token, err := config.Exchange(context.Background(), code)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        log.Println("w is:", *token)
        e := json.NewEncoder(w)
        e.SetIndent("", "  ")
        e.Encode(*token)
    })
    //------------------------------client.go--------------------------------------------//
    //------------------------------server.go--------------------------------------------//
    manager := manage.NewDefaultManager()
    // token store
    manager.MustTokenStorage(store.NewMemoryTokenStore())

    clientStore := store.NewClientStore()
    clientStore.Set("222222", &models.Client{
        ID:     "222222",
        Secret: "22222222",
        Domain: "",
    })
    manager.MapClientStorage(clientStore)

    srv := server.NewServer(server.NewConfig(), manager)
    srv.SetUserAuthorizationHandler(userAuthorizeHandler)

    srv.SetInternalErrorHandler(func(err error) (re *errors.Response) {
        log.Println("Internal Error:", err.Error())
        return
    })

    srv.SetResponseErrorHandler(func(re *errors.Response) {
        log.Println("Response Error:", re.Error.Error())
    })

    http.HandleFunc("/login", loginHandler)
    http.HandleFunc("/auth", authHandler)

    http.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
        log.Println("/authorize")
        requestbody, _ := ioutil.ReadAll(r.Body)
        log.Println("request body is", requestbody)
        log.Println("request url is", r.RequestURI)
        err := srv.HandleAuthorizeRequest(w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
        }
    })

    http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
        log.Println("/token")

        err := srv.HandleTokenRequest(w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })
    //------------------------------server.go--------------------------------------------//
    http.ListenAndServe(":8080", nil)

}

func userAuthorizeHandler(w http.ResponseWriter, r *http.Request) (userID string, err error) {
    log.Println("userAuthorizeHandler")
    us, err := globalSessions.SessionStart(w, r)
    uid := us.Get("UserID")
    if uid == nil {
        if r.Form == nil {
            r.ParseForm()
        }
        us.Set("Form", r.Form)
        w.Header().Set("Location", "/login")
        w.WriteHeader(http.StatusFound)
        return
    }
    userID = uid.(string)
    us.Delete("UserID")
    return
}
func loginHandler(w http.ResponseWriter, r *http.Request) {

    // do whatever you need to do
    if r.Method == "POST" {
        fmt.Println("login post method")
        us, err := globalSessions.SessionStart(w, r)
        if err != nil {
            fmt.Println("err:", err)
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        us.Set("LoggedInUserID", "000000")
        w.Header().Set("Location", "/auth")
        w.WriteHeader(http.StatusFound)
        return
    }
    myvar := map[string]interface{}{"MyVar": "hiiiiiiiiiiii"}
    outputHTML(w, "static/login.html", myvar)
}

func authHandler(w http.ResponseWriter, r *http.Request) {
    log.Println("authHandler")
    log.Println("request url is", r.RequestURI)
    log.Println("request method", r.Method)
    requestbody, _ := ioutil.ReadAll(r.Body)
    log.Println("request body is", string(requestbody))
    log.Println("request body is", requestbody)
    us, err := globalSessions.SessionStart(w, r)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    log.Println("LoggedInUserID:", us.Get("LoggedInUserID"))
    if us.Get("LoggedInUserID") == nil {
        w.Header().Set("Location", "/login")
        w.WriteHeader(http.StatusFound)
        return
    }
    if r.Method == "POST" {
        form := us.Get("Form").(url.Values)
        log.Println("form values entered are", form)
        u := new(url.URL)
        u.Path = "/authorize"
        u.RawQuery = form.Encode()
        w.Header().Set("Location", u.String())
        w.WriteHeader(http.StatusFound)
        us.Delete("Form")
        us.Set("UserID", us.Get("LoggedInUserID"))
        return
    }
    myvar := map[string]interface{}{"MyVar": "redirect url:" + "https://pitangui.amazon.com/spa/skill/account-linking-status.html?vendorId=M256OAZNG882Y2"}
    outputHTML(w, "static/auth.html", myvar)
}

func outputHTML(w http.ResponseWriter, filename string, data interface{}) {
    t, err := template.ParseFiles(filename)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    if err := t.Execute(w, data); err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
}

I am able to achieve oauth by this example but now I want to implement implicit grant oauth2 with this example. Assuming this example is not implicit grant instead response_type=code

  • 写回答

1条回答 默认 最新

  • dqbjvg2518 2017-04-20 20:48
    关注

    To achieve implicit grant you just need response_type and client_id. See RFC6749 . Here is the sample GET request

     GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
            &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
        Host: server.example.com
    

    You can test it first using Curl. Here is the Curl

    curl --data "response_type=token&client_id=227a1cb1&state=xyz" https://hosturl/oauth2/authorize
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Excel发现不可读取的内容
  • ¥15 UE5#if WITH_EDITOR导致打包的功能不可用
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?
  • ¥15 电磁场的matlab仿真
  • ¥15 mars2d在vue3中的引入问题
  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面
  • ¥15 算法题:数的划分,用记忆化DFS做WA求调
  • ¥15 chatglm-6b应用到django项目中,模型加载失败
  • ¥15 CreateBitmapFromWicBitmap内存释放问题。