问题描述:

I'm using PHPoAuthLib along with GitHub to provide a simple OAuth signon system to my PHP web app. I've copied the example but have run into a problem: a redirect from GitHub is not processed by the browser.

My app successfully redirects to the GitHub authorisation page, which looks like this:

https://github.com/login/oauth/authorize?type=web_server&client_id=516xxx7dd9fda3113ef&redirect_uri=http%3A%2F%2Fawooga.local%2Fauth&response_type=code&scope=user%3Aemail

GitHub generates a page which then, amongst a large number of headers, includes this:

Location: http://awooga.local/auth?code=5fb910f67xxxxx91003

However, this is not processed by the browser. At first I thought it was a problem in the Slim framework, which I am also using. I therefore cut this out, and the problem persisted. I then tried wget on the GitHub URL and find that GitHub has generated an error page, which includes this very general error:

<div id="ajax-error-message" class="flash flash-error">

<span class="octicon octicon-alert"></span>

<a href="#" class="octicon octicon-x flash-close js-ajax-error-dismiss" aria-label="Dismiss error"></a>

Something went wrong with that request. Please try again.

</div>

That would explain why it doesn't work in the browser -- you can't do a Location redirect if HTML has been sent. However, the odd thing is that if I take the redirect URL and paste it manually into my browser, it transpires the authentication has actually worked. Thus, as far as I can tell, GitHub has no reason to complain of a problem.

(In case it is not clear, the http://awooga.local domain works fine on my machine - it is set up in local DNS to point to 127.0.0.1).

This question sounds similar, but the solution that worked in that case has not worked in mine (and I can't see how it would make a difference: the author suggests the GH sign-on URL should be a direct link in the app, rather than a redirect).


Post script 1: I wondered whether GH might have found the local-only domain problematic. To test this theory, I've overwritten a real domain with a 127.0.0.1 entry in my /etc/hosts, swapped out the credentials so they match the registered app on GH, and tried again. I get exactly the same behaviour: the redirect is received but not performed. I assume what is happening is what has previously been revealed via wget - a non-specific error in the HTML response is preventing the redirect from operating.


Post script 2: I have ruled out the OAuth library. I've used a variation of an answer below to use raw cURL operations in PHP, which does the same as above -- the Location header is stymied possibly because GH reports a non-specific problem in an HTML response. Since I use a direct URL to GH's /login/oauth/authorize endpoint I can't see what might be going wrong. I then fish out the location from the response, paste it into my browser, and it works fine - it fetches an access token from GitHub, which can then be used to run a user call. All my user info is obtained successfully.

I'm adding some request/response headers from Firefox, in case it helps shed light on the problem:

https://github.com/login/oauth/authorize?client_id=xxx&redirect_uri=http://awooga.local/auth2.php

Request:

Host:"github.com"

User-Agent:"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0"

Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

Accept-Language:"en-gb,en;q=0.5"

Accept-Encoding:"gzip, deflate"

Referer:"http://awooga.local/auth"

Cookie:"logged_in=yes; <stripped for security>"

DNT:"1"

Connection:"keep-alive"

Response:

Cache-Control:"no-cache, private"

Content-Type:"text/html; charset=utf-8"

Date:"Sat, 27 Dec 2014 19:31:59 GMT"

Location:"http://awooga.local/auth2.php?code=zzz"

Server:"GitHub.com"

Set-Cookie:"user_session=aaa; path=/; expires=Sat, 10-Jan-2015 19:31:59 GMT; secure; HttpOnly

_gh_sess=??; path=/; secure; HttpOnly"

Status:"302 Found"

Strict-Transport-Security:"max-age=31536000; includeSubdomains; preload"

Transfer-Encoding:"chunked"

Vary:"X-PJAX, Accept-Encoding"

X-Content-Type-Options:"nosniff"

X-Frame-Options:"deny"

X-GitHub-Request-Id:"(stripped)"

X-GitHub-Session-Id:"(stripped)"

X-GitHub-User:"halfer"

X-Rack-Cache:"miss"

X-Request-Id:"(stripped)"

X-Runtime:"0.016812"

X-Served-By:"(stripped)"

X-XSS-Protection:"1; mode=block"

content-security-policy:"default-src *; script-src assets-cdn.github.com collector-cdn.github.com; object-src assets-cdn.github.com; style-src 'self' 'unsafe-inline' 'unsafe-eval' assets-cdn.github.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.githubusercontent.com *.gravatar.com *.wp.com; media-src 'none'; frame-src 'self' render.githubusercontent.com gist.github.com www.youtube.com player.vimeo.com checkout.paypal.com; font-src assets-cdn.github.com; connect-src 'self' ghconduit.com:25035 live.github.com uploads.github.com www.google-analytics.com s3.amazonaws.com"

x-ua-compatible:"IE=Edge,chrome=1"


Post script 3: I've tried the same on another browser on my system, Midori, and it works fine. So it is either a browser issue (or perhaps Midori is happy to redirect despite having received HTML content in a redirection reply).

网友答案:

http://awooga.local is not a real domain.

check out a small example here: http://githubv3.herokuapp.com/

========Update=========

Sorry about the miss leading over there ;(

Here is the sample code I wrote:

index.html

<html>
    <head>          
    </head>
    <body>
        hi,there

        <br>

        <!-- replace with your own client_id and redirect uri -->
        <a href="https://github.com/login/oauth/authorize?client_id=YourClientId&redirect_uri=http://www.sites.com/github/callback.php">github login</a>
    </body>
</html>

callback.php

<?php

if(isset($_GET['code'])){

    $code = $_GET['code'];

    // post to get access_token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, true);
    // your own client_id and client_secret
    $url = "https://github.com/login/oauth/access_token?client_id=YourClientId&client_secret=YourClientSecret&code=$code";
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Accept: application/json'
        ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    if($result === false){
        echo 'curl error'.curl_error($ch);
    }else{
        $response = json_decode($result, true);
        $accessToken = $response['access_token'];

        if(!empty($accessToken)){

            $ch = curl_init();
            $url = "https://api.github.com/user?access_token=$accessToken";
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                    'Accept: application/vnd.github.v3+json'
                ));
            curl_setopt($ch, CURLOPT_USERAGENT,  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.6 Safari/537.11");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $result = curl_exec($ch);
            if($result === false){
                echo 'curl error'.curl_error($ch);  
            }else{
                echo 'auth user info:<br>';
                var_dump($result);
            }
        }else{
            echo 'access_token empty';
        }
    }
    curl_close($ch);
}else{
    echo 'no code';
}
网友答案:

I have fixed it, though I am not entirely sure what was going wrong. I tried Midori, and then a separate install of Firefox, and both worked fine. I thus disabled some plugins in my usual Firefox install and it started redirecting correctly.

Strangely I re-enabled the offending plugin(s) and now cannot get it to fail again. Perhaps the process of disablement and re-enablement reset them in some fashion? It seems to have been Foxy Proxy that was responsible, but since I have re-enabled it without problems I am now not so sure.

相关阅读:
Top