Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seems Twitter auth doesn't work without oob but with callback url #14

Closed
shalakhin opened this issue Nov 19, 2013 · 2 comments
Closed

Comments

@shalakhin
Copy link

Looking at Twitter example I tried to implement it for my project. Below you can see 2 functions:

  1. ask verification code
  2. take verification code and retrieve token

But I am getting:

2013/11/19 05:19:39 httpExecute: HTTP response is not 200/OK as expected. Actual response:
    Response Status: '401 Unauthorized'
    Response Code: 401
    Response Body: Invalid request token
    Requst Headers: [key: Authorization, val: OAuth oauth_consumer_key="eGhxxEwyi1AOgQhtQNi1g",oauth_nonce="6812501655763588603",oauth_signature="5%2Ffqo84h2tfujYk3q6x13dpdaY8%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1384831178",oauth_token="2SzuHTzXp93rj4TJJXy0sHYs2Wg7l9pTpNE3oLs8",oauth_verifier="",oauth_version="1.0"][key: Content-Length, val: 0]
exit status 1

My code:

func AskTwitterVerificationCode(w http.ResponseWriter, r *http.Request) {
        c := oauth.NewConsumer(
                config.TwitterConsumerKey,
                config.TwitterConsumerSecret,
                oauth.ServiceProvider{
                        RequestTokenUrl: "http://api.twitter.com/oauth/request_token",
                        AuthorizeTokenUrl: "https://api.twitter.com/oauth/authorize",
                        AccessTokenUrl: "https://api.twitter.com/oauth/access_token",
                },
        )
        if config.Debug {
                c.Debug(true)
        }

        var requestUrl, tokenUrl string
        if config.Debug {

                tokenUrl = "http://myapp.com:"+strconv.Itoa(config.Port)+"/auth/twitter/callback"
        } else {
                tokenUrl = "http://myapp.com/auth/twitter/callback"
        }
        var err error
        _, requestUrl, err = c.GetRequestTokenAndUrl(tokenUrl)
        if err != nil {
                log.Fatal(err)
        }
        http.Redirect(w, r, requestUrl, http.StatusMovedPermanently)
}

func GetTwitterToken(w http.ResponseWriter, r *http.Request) {
        c := oauth.NewConsumer(
                config.TwitterConsumerKey,
                config.TwitterConsumerSecret,
                oauth.ServiceProvider{
                        RequestTokenUrl: "http://api.twitter.com/oauth/request_token",
                        AuthorizeTokenUrl: "https://api.twitter.com/oauth/authorize",
                        AccessTokenUrl: "https://api.twitter.com/oauth/access_token",
                },
        )
        if config.Debug {
                c.Debug(true)
        }

        var tokenUrl string
        var requestToken *oauth.RequestToken
        if config.Debug {

                tokenUrl = "http://myapp.com:"+strconv.Itoa(config.Port)+"/auth/twitter/callback"
        } else {
                tokenUrl = "http://myapp.com/auth/twitter/callback"
        }
        var err error
        requestToken, _, err = c.GetRequestTokenAndUrl(tokenUrl)
        if err != nil {
                log.Fatal(err)
        }
        values := r.URL.Query()
        verificationCode := values.Get("oauth_verifier")
        log.Println(verificationCode)
        accessToken, err := c.AuthorizeToken(requestToken, verificationCode)
        if err != nil {
                log.Fatal(err)
        }
        fmt.Fprintf(w, accessToken.Token, " and ", accessToken.Secret)
}
@mrjones
Copy link
Owner

mrjones commented Nov 26, 2013

Hello, and thanks for the bugreport! Sorry for not getting to it sooner.

The basic issue is:

  1. GetRequestTokenAndUrl returns a RequestToken and a URL
  2. The user is sent to that URL (and is subsequently redirected back to us along with a verification code).
  3. When calling AuthorizeToken: the RequestToken must be the same token from step 1. (There's an association between the request token, and some parameters in the URL we redirect the user to.)

So, it's not going to work to call GetRequestTokenAndUrl a second time to get a new RequestToken. Instead we must save the token from the first call.

I modified your code and wrote up a quick example of doing so here:
https://github.com/mrjones/oauth/blob/master/examples/twitterserver/twitterserver.go
It's not very elegant (it just uses a global variable), but I just wanted something that worked to demonstrate the technique.

Please let me know if this helps you get your code working! If you're happy, we can close out this bug.

One other unrelated/side note:
When redirecting the user: you probably want to consider "http.StatusTemporaryRedirect" instead of "http.StatusMovedPermanently". They both cause the user to be redirected. However, the second status will (usually) cause the browser to skip over your server, and redirect straight to twitter (this is bad because GetRequestTokenAndUrl won't be called!). The temporary redirect status will ensure the browser always checks your server first, before being redirected.

@shalakhin
Copy link
Author

It helped! Thank you! It works now. Issue can be closed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants