dermesser / yup-oauth2

An oauth2 client implementation providing the Device, Installed, Service Account, and several more flows.
https://docs.rs/yup-oauth2/
Apache License 2.0
218 stars 114 forks source link

Redirect URI `urn:ietf:wg:oauth:2.0:oob` should not be used in non-InstalledInteractive flow #66

Open phrohdoh opened 7 years ago

dermesser commented 7 years ago

?

It shouldn't be: https://github.com/dermesser/yup-oauth2/blob/master/src/installed.rs#L197

phrohdoh commented 7 years ago

Given this data (manifest, code, secret):

[package]
name = "google_test"
version = "0.1.0"
authors = ["Taryn Hill <taryn@phrohdoh.com>"]

[dependencies]
yup-oauth2 = "1.0"
hyper = "0.10"
hyper-rustls = "0.6"
google-calendar3 = "1.0"
extern crate hyper;
extern crate hyper_rustls;
extern crate yup_oauth2 as auth;
extern crate google_calendar3 as gcal;

use std::path::Path;

use hyper::net::HttpsConnector;

use auth::{Authenticator, FlowType, ApplicationSecret, DiskTokenStorage, DefaultAuthenticatorDelegate, read_application_secret};
use gcal::CalendarHub;

const CLIENT_SECRET_FILE: &'static str = "client_secret.json";

fn main() {
    let secret = read_application_secret(Path::new(CLIENT_SECRET_FILE)).unwrap();
    let client = hyper::Client::with_connector(HttpsConnector::new(hyper_rustls::TlsClient::new()));
    let authenticator = Authenticator::new(&secret,
                                           DefaultAuthenticatorDelegate,
                                           client,
                                           DiskTokenStorage::new(&"token_store.json".to_string()).unwrap(),
                                           Some(FlowType::InstalledRedirect(5000)));
    let client = hyper::Client::with_connector(HttpsConnector::new(hyper_rustls::TlsClient::new()));
    let hub = CalendarHub::new(client, authenticator);

    let (_resp, list_result) = hub.calendar_list().list().doit().unwrap();

    for cal in list_result.items.unwrap_or(vec![]) {
        println!("{} ({})",
                 cal.summary.unwrap_or("<no summary>".to_string()),
                 cal.id.unwrap_or("<no id>".to_string()));
    }
}
{
    "web": {
        "client_id": "1047850706592-d7ljgqu55ot9usc0kc8t2ihbueqrskta.apps.googleusercontent.com",
        "project_id": "calendar-api-test-171020",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://accounts.google.com/o/oauth2/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "<my secret>",
        "redirect_uris": [
            "http://localhost"
        ]
    }
}

I get:

Please direct your browser to https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/calendar.readonly&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=1047850706592-d7ljgqu55ot9usc0kc8t2ihbueqrskta.apps.googleusercontent.com, follow the instructions and enter the code displayed here:
phrohdoh commented 7 years ago

Perhaps this library wants me to use a service account but according to https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps a service account is not what I want.

I want to make requests on behalf of the user without them having to directly interact with my application on a regular basis (just allow auth and of course revoke auth if they decide to, but that is done via Google's interfaces as far as the user is concerned).

dermesser commented 7 years ago

Calendar doesn't want a service account, and even if it would -- that would return an error, not present this.

One explanation would be that the HTTP server fails to start, so that the InstalledFlow falls back to the interactive flow: https://github.com/dermesser/yup-oauth2/blob/master/src/installed.rs#L100. Is there by any chance anything else listening on port 5000? (a UPnP service, for example)

phrohdoh commented 7 years ago

The only thing listening on port 5000 is a flask app I threw together to get the redirect auth code from Google.

dermesser commented 7 years ago

You don't need that server. yup-oauth2 starts its own HTTP server to catch the code. And in this case it can't, because there's already your server listening on the port it wants to listen on.