Search code examples
govkmartini

social network vk auth with martini


I am trying to use vk auth with martini. But have error on compile:

/goPath/vkAuthTry2.go:38: undefined: YourRedirectFunc

The question is how to define YourRedirectFunc function. Or if ask more widely I need working example of martini app with vk social network authentication or if even more widely an example of any golang website using vk authentication.

Full code:

package main

import (
    "github.com/go-martini/martini"
    "github.com/yanple/vk_api"
    "net/http"
)

var api vk_api.Api

func prepareMartini() *martini.ClassicMartini {
    m := martini.Classic()
    m.Get("/somePage", func(w http.ResponseWriter, r *http.Request) {
        //  And receive token on the special method (redirect uri)
        currentUrl := r.URL.RequestURI() // for example "yoursite.com/get_access_token#access_token=3304fdb7c3b69ace6b055c6cba34e5e2f0229f7ac2ee4ef46dc9f0b241143bac993e6ced9a3fbc111111&expires_in=0&user_id=1"
        accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(currentUrl)
        if err != nil {
            panic(err)
        }
        api.AccessToken = accessToken
        api.UserId = userId
        api.ExpiresIn = expiresIn
        w.Write([]byte("somePage"))
    })
    return m
}

func main() {
    authUrl, err := api.GetAuthUrl(
        "domain.com/method_get_access_token", // redirect URI
        "token",        // response type
        "4672050",      // client id
        "wall,offline", // permissions https://vk.com/dev/permissions
    )
    if err != nil {
        panic(err)
    }
    YourRedirectFunc(authUrl)
    prepareMartini().Run()
}

Update

I edited my code according to @Elwinar's answer:

package main

import (
    "fmt"
    "github.com/go-martini/martini"
    "github.com/yanple/vk_api"
    "net/http"
)

var api vk_api.Api

func prepareMartini() *martini.ClassicMartini {
    m := martini.Classic()
    // This handler redirect the request to the vkontact system, which
    // will perform the authentification then redirect the request to
    // the URL we gave as the first paraemeter of the GetAuthUrl method
    // (treated by the second handler)
    m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) {
        var api vk_api.Api
        authUrl, err := api.GetAuthUrl("http://localhost:3000/vk/token", "token", "4672050", "wall,offline")
        if err != nil {
            panic(err)
        }

        http.Redirect(w, r, authUrl, http.StatusFound)
    })

    // This handler is the one that get the actual authentification
    // information from the vkontact api. You get the access token,
    // userid and expiration date of the authentification session.
    // You can do whatever you want with them, generally storing them
    // in session to be able to get the actual informations later using
    // the access token.
    m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) {
        accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String())
        if err != nil {
            panic(err)
        }
        fmt.Println(accessToken)
        fmt.Println(userId)
        fmt.Println(expiresIn)
    })
    return m
}

func main() {
    prepareMartini().Run()
}

now no complie errors, but still cannot login. When I opened http://localhost:3000/vk/auth I was redirected on page...

https://oauth.vk.com/authorize?client_id=MY_APP_ID&redirect_uri=localhost%3A3000%2Fvk%2Ftoken&response_type=token&scope=wall%2Coffline

... and got the following browser output:

{"error":"invalid_request","error_description":"redirect_uri is incorrect, check application domain in the settings page"}

Of course instead of 4672050 I pasted my app id. This app was specially generated for localhost:3000. Maybe I need to paste somewhere my private key for oauth like pYFR2Xojlkad87880dLa.

Update 2

@qwertmax's answer almost works. I have successfully logged in by vk, but my code prints empty lines instead of userId and another user information:

 accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String())

fmt.Println(accessToken)
fmt.Println(userId)
fmt.Println(expiresIn)

Solution

  • Thanks for answer, I added example @qwertmax and fixed bug for parse fragment of url. Please update package and see example.

    package main
    // Thanks @qwertmax for this example
    // (http://stackoverflow.com/questions/29359907/social-network-vk-auth-with-martini)
    
    
    import (
        "log"
        "github.com/go-martini/martini"
        "github.com/yanple/vk_api"
        "net/http"
    )
    
    var api vk_api.Api
    
    func prepareMartini() *martini.ClassicMartini {
        m := martini.Classic()
    
        m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) {
            authUrl, err := api.GetAuthUrl(
            "http://localhost:3000/vk/token",
            "app client id",
            "wall,offline")
    
            if err != nil {
                panic(err)
            }
    
            http.Redirect(w, r, authUrl, http.StatusFound)
        })
    
        m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) {
            code := r.URL.Query().Get("code")
    
            err := api.OAuth(
            "http://localhost:3000/vk/token", // redirect uri
            "app secret key",
            "app client id",
            code)
            if err != nil {
                panic(err)
            }
            http.Redirect(w, r, "/", http.StatusFound)
        })
    
        m.Get("/", func(w http.ResponseWriter, r *http.Request) string {
            if api.AccessToken == "" {
                return "<a href='/vk/auth'>Авторизоваться</a>"
            }
    
            // Api have: AccessToken, UserId, ExpiresIn
            log.Println("[LOG] martini.go:48 ->", api.AccessToken)
    
            // Make query
            params := make(map[string]string)
            params["domain"] = "yanple"
            params["count"] = "1"
    
            strResp, err := api.Request("wall.get", params)
            if err != nil {
                panic(err)
            }
            return strResp
        })
        return m
    }
    
    func main() {
        prepareMartini().Run()
    }
    

    Update 1: Update your package with command: go get -u github.com/yanple/vk_api Thanks for the comment.