Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
No such thing as a small change
 
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
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 avoiding work at the Monastery: (8)
As of 2014-04-17 11:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (445 votes), past polls