DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Google OAuth 2.0 on Windows Phone

Google OAuth 2.0 on Windows Phone

Pieter De Rycke user avatar by
Pieter De Rycke
·
Mar. 13, 13 · Interview
Like (0)
Save
Tweet
Share
5.22K Views

Join the DZone community and get the full member experience.

Join For Free

introduction

oauth is a protocol for authorization. it allows desktop, mobile and web applications to access web resources (mostly rest services) on behalf of a user. the protocol permits this without the user having to share its credentials (typically, a username and password pair) with the application. oauth is a widely implemented protocol. various companies (like facebook, twitter, google, microsoft, dropbox …) use it to protect their apis.

in this article, i will explain how we can implement support for google oauth in a windows phone application.

how does oauth work

in a nutshell when developing a mobile application, a developer must register its application to the vendor of the service (in our case google) who will assign a clientid and a clientsecret to the application.

the login flow starts with the application opening an embedded web browser control. this web control must load a specific google login page. in the query string, the clientid of the application and the requested scopes are sent to the login page. scopes are the actions the application wants to perform on behalf of the user. google will handle the user authentication and consent, but at the end an authorization code is sent to the web browser control (using the “title” of the final html page).

oauth windows phone authorization flow

after having received the authorization code, the application can exchange this for an access token and a refresh token. the access token can be used by the application to perform the necessary operations on behalf of the user. the refresh token must be stored for future use; it allows to request a new access token when the previous one expired.

implementing google oauth on windows phone

you will have to register your application at https://code.google.com/apis/console#access . this will provide you a clientid and clientsecret that you can use to identity your application to the user when performing the oauth flow.

my implementation consists of 2 big components, a class called “oauthauthorization” and a windows phone page called “logingpage”.

when the developer calls the method “authorize” of the oauthauthorization class, the login page is opened on the screen. this page will show the embedded web browser control full screen (an important detail is that scripting support for this embedded must be activated; by default it is disabled). the google login page is opened and navigated event handler is attached to the browser control. when the web browser control is redirected to the success page of the login flow, the authorization code is extracted and the login page is closed.

public partial class loginpage : phoneapplicationpage
{
    public loginpage()
    {
        initializecomponent();
    }

    protected override void onnavigatedto(navigationeventargs e)
    {
        base.onnavigatedto(e);

        idictionary parameters = this.navigationcontext.querystring;

        string authendpoint = parameters["authendpoint"];
        string clientid = parameters["clientid"];
        string scope = parameters["scope"];

        string uri = string.format("{0}?response_type=code&client_id={1}&redirect_uri={2}&scope={3}",
            authendpoint,
            clientid,
            "urn:ietf:wg:oauth:2.0:oob",
            scope);

        webbrowser.navigate(new uri(uri, urikind.absolute));
    }

    private void webbrowser_navigated(object sender, navigationeventargs e)
    {
        string title = (string)webbrowser.invokescript("eval", "document.title.tostring()");

        if (title.startswith("success"))
        {
            string authorizationcode = title.substring(title.indexof('=') + 1);
            phoneapplicationservice.current.state["mobileoauth.authorizationcode"] = authorizationcode;

            navigationservice.goback();
        }
    }
}

using the client id and the client secret, the oauthauthorization class will call a google rest api to exchange the authorization code for an access token and a refresh token.

public class oauthauthorization
{
    private readonly string authendpoint;
    private readonly string tokenendpoint;
    private readonly phoneapplicationframe frame;

    public oauthauthorization(string authendpoint, string tokenendpoint)
    {
        this.authendpoint = authendpoint;
        this.tokenendpoint = tokenendpoint;
        this.frame = (phoneapplicationframe)(application.current.rootvisual);
    }

    public async task authorize(string clientid, string clientsecret, ienumerable scopes)
    {
        string uri = string.format("/mobileoauth;component/loginpage.xaml?authendpoint={0}&clientid={1}&scope={2}",
                                    authendpoint,
                                    clientid,
                                    string.join(" ", scopes));

        semaphoreslim semaphore = new semaphoreslim(0, 1);

        observable.fromevent(
            h => new navigatingcanceleventhandler(h),
            h => this.frame.navigating += h,
            h => this.frame.navigating -= h)
                    .skipwhile(h => h.eventargs.navigationmode != navigationmode.back)
                    .take(1)
                    .subscribe(e => semaphore.release());

        frame.navigate(new uri(uri, urikind.relative));

        await semaphore.waitasync();

        string authorizationcode = (string)phoneapplicationservice.current.state["mobileoauth.authorizationcode"];

        return await requestaccesstoken(authorizationcode, clientid, clientsecret);
    }

    public async task refreshaccesstoken(string clientid, string clientsecret, string refreshtoken)
    {
        httpwebrequest httprequest = (httpwebrequest)webrequest.create(tokenendpoint);
        httprequest.method = "post";
        httprequest.contenttype = "application/x-www-form-urlencoded";

        using (stream stream = await httprequest.getrequeststreamasync())
        {
            using (streamwriter writer = new streamwriter(stream))
            {
                writer.write("refresh_token=" + uri.escapedatastring(refreshtoken) + "&");
                writer.write("client_id=" + uri.escapedatastring(clientid) + "&");
                writer.write("client_secret=" + uri.escapedatastring(clientsecret) + "&");
                writer.write("grant_type=refresh_token");
            }
        }

        using (webresponse response = await httprequest.getresponseasync())
        {
            using (streamreader streamreader = new streamreader(response.getresponsestream()))
            {
                string result = streamreader.readtoend();
                tokenpair tokenpair = jsonconvert.deserializeobject(result);
                tokenpair.refreshtoken = refreshtoken;

                return tokenpair;
            }
        }
    }

    private async task requestaccesstoken(string authorizationcode, string clientid,
                                            string clientsecret)
    {
        httpwebrequest httprequest = (httpwebrequest)webrequest.create(tokenendpoint);
        httprequest.method = "post";
        httprequest.contenttype = "application/x-www-form-urlencoded";

        using (stream stream = await httprequest.getrequeststreamasync())
        {
            using (streamwriter writer = new streamwriter(stream))
            {
                writer.write("code=" + uri.escapedatastring(authorizationcode) + "&");
                writer.write("client_id=" + uri.escapedatastring(clientid) + "&");
                writer.write("client_secret=" + uri.escapedatastring(clientsecret) + "&");
                writer.write("redirect_uri=" + uri.escapedatastring("urn:ietf:wg:oauth:2.0:oob") + "&");
                writer.write("grant_type=authorization_code");
            }
        }

        using (webresponse response = await httprequest.getresponseasync())
        {
            using (streamreader streamreader = new streamreader(response.getresponsestream()))
            {
                string result = streamreader.readtoend();
                return jsonconvert.deserializeobject(result);
            }
        }
    }
}

using the oauth implementation

the implemented framework is simple in usage. the following example shows how to use it:

// request an access token
oauthauthorization authorization = new oauthauthorization(
    "https://accounts.google.com/o/oauth2/auth", 
    "https://accounts.google.com/o/oauth2/token");
tokenpair tokenpair = await authorization.authorize(
    clientid,
    clientsecret,
    new string[] {googlescopes.cloudprint, googlescopes.gmail});

// request a new access token using the refresh token (when the access token was expired)
tokenpair refreshtokenpair = await authorization.refreshaccesstoken(
    clientid,
    clientsecret,
    tokenpair.refreshtoken);

the access token must be sent using the authorization: bearer http header when calling a google api.

conclusion

implementing oauth support on windows phone is quite simple to do. the authentication and user consent logic is handled by google and integrated into an app by embedding the web browser control. once a token is obtained, the application can perform the requested actions on behalf of the user until the user revokes the access for the application.

i have put the source code on github as a reusable framework. the oauth framework should also be usable with the various other oauth providers.

you can find it at: https://github.com/pieterderycke/mobileoauth .



authentication Windows Phone security Google (verb) mobile app

Published at DZone with permission of Pieter De Rycke, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Unlocking the Power of Elasticsearch: A Comprehensive Guide to Complex Search Use Cases
  • Real-Time Analytics for IoT
  • Building a Real-Time App With Spring Boot, Cassandra, Pulsar, React, and Hilla
  • Steel Threads Are a Technique That Will Make You a Better Engineer

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: