Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

OAuth2 WNS

by DaisyLou (Acolyte)
on Sep 16, 2013 at 16:16 UTC ( #1054310=perlquestion: print w/ replies, xml ) Need Help??
DaisyLou has asked for the wisdom of the Perl Monks concerning the following question:

~~~~~~~~~~~~~~~~ edit: SOLUTION BELOW. ~~~~~~~~~~~~~~~~ I'm trying to send a WNS notification via Perl with the following code using OAuth2. When I step through the code, it appends the site to make it https://login.live.com/oauth/authorize, which (I think) is causing it to fail. Any suggestions on how to send WNS notifications from Perl?
my $auth = Net::OAuth2::Profile::Password->new( site => 'https://login.live.com/' , site_path => '/accesstoken.srf' , client_id => uri_escape('ms-app://xxxxx') , client_secret => uri_escape('yyyyyyyy') , grant_type => 'client_credentials' , scope => 'notify.windows.com' ); my $token = $auth->get_access_token();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I gave up using OAuth2 and rolled my own. Hopefully you folks will find this helpful. You can't just copy and paste, but if you follow the directions in the ##comments, you should be 90% there. This sends a Toast message via WNS to a unique ID (in my case, a user ID) associated with a WNS Channel. The XML payload can obviously be changed to send badges or whatever you want. I store everything in a database. You can use constants, except for the access token which changes, and you'll need to find some way to persist it. To use: sendPushNotificationToast($uniqID);. This will resolve the uniqID to its corresponding WNS channel(which again, in my case is stored in the database next to uniqID), and try to send a push notification.
use DBI; use URI::Escape; use LWP::Simple; use JSON qw( decode_json ); use Data::Dumper; ################################################################## sub getWNSChannel { ## The "ID" here is an ID associated with a WNS channel ## An ID is a unique user or computer my ($id) = @_; ## I persist the WNSURI in a database. ## Fetch WNSURI from persistent store, using ID as a key # Sanity check if ($WNSChannel =~ m#^https://.*notify\.windows\.com\/\?#) { return $WNSChannel; } return $WNS_OFFLINE; } ################################################################## sub sendWNSPost { my ( $server_endpoint, $payload, $hdr_Authorization, $hdr_ContentType, $hdr_XWNSType, $hdr_XWNSCachePolicy, $hdr_XWNSRequestForStatus, $hdr_XWNSTag, $hdr_XWNSTTL ) = @_; my $ua = LWP::UserAgent->new; $ua->agent("ArbitraryUserAgent/0.1 "); my $req = HTTP::Request->new(POST => $server_endpoint); $req->header('Authorization' => $hdr_Authorization + ) if defined $hdr_Authorization; $req->header('Content-Type' => $hdr_ContentType + ) if defined $hdr_ContentType; $req->header('X-WNS-Type' => $hdr_XWNSType + ) if defined $hdr_XWNSType; $req->header('X-WNS-Cache-Policy' => $hdr_XWNSCachePolic +y ) if defined $hdr_XWNSCachePolicy; $req->header('X-WNS-RequestForStatus' => $hdr_XWNSRequestFor +Status ) if defined $hdr_XWNSRequestForStatus; $req->header('X-WNS-Tag' => $hdr_XWNSTag + ) if defined $hdr_XWNSTag; $req->header('X-WNS-TTL' => $hdr_XWNSTTL + ) if defined $hdr_X-WNS-TTL; $req->content($payload); return $ua->request($req); } sub getNewAccessToken { ## Fetch WNS client ID, secret, and URI from persistent store ## (or you can hard code them/put in config file, whatever) ## and put them into client_id, client_secret URL encoded $authenticationUri = "https://login.live.com/accesstoken.srf"; $client_id = uri_escape($client_id); $client_secret = uri_escape($client_secret); my $payload = "grant_type=client_credentials&client_id=$client +_id&client_secret=$client_secret&scope=notify.windows.com"; my $resp = sendWNSPost( $authenticationUri, $payload, undef, 'application/x-www-form-urlencoded', + # Content-Type undef, undef, undef, undef, undef); my $decoded_json = decode_json( $resp->content ); my $access_token = $decoded_json->{'access_token'}; if ($resp->is_success) { ## Update the access token in the database/persistent +store } else { ## Yeeps! Something went wrong. Send an alert, log, e +tc here. } } sub getWNSAccessToken { # Get the current access token ## Nothing fancy. ## Just fetch current WNS access token from persistent store a +nd return it return $accessToken; } sub sendPushNotificationToast { my ($id) = @_; my $WNSChannel = getWNSChannel($id); my $accessToken = getWNSAccessToken(); if ($WNSChannel == $WNS_OFFLINE) { return $WNS_OFFLINE; } # Sanity check if ($WNSChannel !~ /^https.*notify\.windows\.com/) { return $WNS_ERR; } # Get customer details for toast my $toastLine1 = "Toast Line 1"; my $toastLine2 = "Toast Line 2"; my $payload = "<toast duration='long'><visual version='1'><bin +ding template='ToastText02'><text id='1'>$toastLine1</text><text id=' +2'>$toastLine2</text></binding></visual></toast>"; my $resp; $resp = sendWNSPost ($WNSChannel, $payload, "Bearer $accessTok +en", "text/xml", "wns/toast", "no-cache", "true", undef, undef); if ($resp->is_error) { ## If at first you don't succeed, ## get a new access token and try again. getNewAccessToken(); $accessToken = getWNSAccessToken(); $resp = sendWNSPost ($WNSChannel, $payload, "Bearer $a +ccessToken", "text/xml", "wns/toast", "no-cache", "true", undef, 600) +; # TTL = 10 minutes here } if ($resp->is_success) { my $connectionStatus = $resp->header('X-WNS-DeviceConn +ectionStatus'); if ($connectionStatus eq 'connected') { return $WNS_OK; } elsif ($connectionStatus eq 'tempdisconnected') { ## Handle 'tempdisconnected' in whatever way y +ou please. return $WNS_OK; # or whatever you want } elsif ($connectionStatus eq 'disconnected') { return $WNS_OFFLINE; } } return $WNS_ERR; } ;

Comment on OAuth2 WNS
Select or Download Code
Replies are listed 'Best First'.
Re: OAuth2 WNS
by Anonymous Monk on Sep 17, 2013 at 08:29 UTC

    When I step through the code, it appends the site to make it https://login.live.com/oauth/authorize, which (I think) is causing it to fail.

    What do the docs (on microsoft) say (in the example)?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1054310]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (19)
As of 2015-07-28 20:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (258 votes), past polls