Can I use Azure AD "businessPhones" in a URL parameter? - url

I am able to use a number of Azure AD profile entity fields in a URL parameter for parsing the logged in user's profile data into a form on our intranet for pre-fill or the like.
For example, ...URL?officelocation=(user.apiProfile.officeLocation)&fullname=(user.fullName)&email=(user.email)&jobtitle=(user.apiProfile.jobTitle).
All of these fields are single string data types according to https://graph.microsoft.com/v1.0/$metadata#users/$entity.
I'd like to know if it's possible to use the first or second value of a collection of strings as a parameter in the URL. And if so, how?
Take the "businessPhones" field for example. I've tried using &userphone=(user.businessPhones[0]) or other formations but am unable to return the field data.
On a page of our intranet which uses Azure AD as the Identity Provider via SAML 2.0 and uses the Microsoft Graph API, I am able to surface almost any user profile data dynamically on the page as content - including those fields which are in an array (or collection of strings), using the below script and html snippet as example.
<p>First name + Last name: <span id="user-firstname" style="font-weight:600;"></span> <span id="user-lastname" style="font-weight:600;"></span></p>
<p>Full name: <span id="user-fullname" style="font-weight:600;"></span></p>
<p>Email address: <span id="user-email" style="font-weight:600;"></span></p>
<p>Job title: <span id="user-jobtitle" style="font-weight:600;"></span></p>
<p>Office Phone: <span id="user-officephone" style="font-weight:600;"></span></p>
<p>Firm Name: <span id="user-firm" style="font-weight:600;"></span></p>
<p>Firm Address: <!--<span id="user-streetaddress" style="font-weight:600;"></span> <span id="user-city" style="font-weight:600;"></span>, <span id="user-postcode" style="font-weight:600;"></span>, --><span id="user-state" style="font-weight:600;"></span></p>
<p>UID: <span id="user-id" style="font-weight:600;"></span></p>
<p>Embedded Page: <span id="text-url" style="font-weight:600;"></span></p>
<script>
$('#user-firstname').html(CONNECTED_USER.firstName);
$('#user-lastname').html(CONNECTED_USER.lastName);
$('#user-fullname').html(CONNECTED_USER.fullName);
$('#user-email').html(CONNECTED_USER.email);
$('#user-jobtitle').html(CONNECTED_USER.apiProfile.jobTitle);
$('#user-officephone').html(CONNECTED_USER.apiProfile.phones[1].value);
$('#user-firm').html(CONNECTED_USER.apiProfile.officeLocation);
/*$('#user-streetaddress').html(CONNECTED_USER.apiProfile.streetAddress);*/
/*$('#user-city').html(CONNECTED_USER.apiProfile.city);*/
/*$('#user-postcode').html(CONNECTED_USER.apiProfile.postalCode);*/
$('#user-state').html(CONNECTED_USER.apiProfile.organizations[0].stateLocation);
$('#user-id').html(CONNECTED_USER.id);
$('#user-url').html(CONNECTED_USER.url);
$('#current-url').attr("href", window.location.href);
$('#text-url').html(window.location.href)
</script>
You can see that I use CONNECTED_USER.apiProfile.phones[1].value and CONNECTED_USER.apiProfile.organizations[0].stateLocation to return the data I wish to show.
Is it possible to do similar with URL parameters?

I think it's based on which language you used for composing the url. For example, in asp.net core, when you got the response from graph api, you can see that the BusinessPhones property is IEnumerable<string>, so you can't use user.businessPhones[0] but BusinessPhones.FirstOrDefault().
And if you compose the url in javascript, it should work when you use user.businessPhones[0], if it doesn't work, you may add console.log(user.businessPhones) to see the data.
By the way if some users has no value for businessPhones property, you may need to consider it.

Related

How can Yahoo Mail be accessed by IMAP using OAuth or OAuth2 authentication

According to developer.yahoo.com/mail/ and IMAP responses:
* OK [CAPABILITY IMAP4rev1 ID MOVE NAMESPACE X-ID-ACLID UIDPLUS LITERAL+ CHILDREN XAPPLEPUSHSERVICE XYMHIGHESTMODSEQ AUTH=PLAIN AUTH=LOGIN AUTH=XOAUTH2 AUTH=XYMCOOKIE AUTH=XYMECOOKIE AUTH=XYMCOOKIEB64 AUTH=XYMPKI] IMAP4rev1 imapgate-1.8.1_01.20166 imap1009.mail.ne1.yahoo.com
Yahoo Mail can be accessed by IMAP using OAuth(2) authentication.
I registered my app on https://developer.yahoo.com/apps/ so I have got Client ID and Client Secret. I didn't find any scopes(API Permissions) related to Mail. Nevertheless I selected all API Permissions which were presented when I registered my app.
I tried to implement both OAuth and OAuth2.
OAuth2:
I cannot get the authorization code for scope "mail-r". When I generate URL(https://api.login.yahoo.com/oauth2/request_auth?client_id=CLIENT_ID&redirect_uri=oob&scope=mail-r&response_type=code) and open it in browser, the page with text "Developers: Please request scope from registered scopes and submit again." is displayed. It works for other scopes. For example, I'm able to get the authorization code for "sdct-r"
OAuth:
I'm able to get an access token. But when I send it with AUTHENTICATE XOAUTH2 command, I get "NO [AUTHENTICATIONFAILED] (#AUTH007) Bad scope" response.
So questions is what scope(s) should be set to access Yahoo Mail using IMAP and OAuth(2)?
Update February 27, 2017: This work-around will not work anymore as Yahoo has unfortunately taken down the cck-form.html page referenced below and does not seem to allow new apps to request mail related API access. Hopefully this changes.
Here is how you can create an App on yahoo with full access to emails. (recently yahoo remove this option from their UI) once proper permissions are in place, getting oauth tokens and accessing mail boxes should be straight forward and I am not covering it here.
Visit https://developer.yahoo.com/oauth/guide/cck-form.html and look for "Here is an example form along with sample values you can use in the form" and copy the example html into a local file and save it. A Copy of the html is available below.
Open the file on browser. fill appropriate info (set scope=ymrf for full mail access) and click on "pop window with debug".
Click on allow on the popup window. Sign in is required if you did not already login to yahoo on the browser.
go to https://developer.yahoo.com/apps/ and you should see your app with appropriate permissions.
<html>
<head>
<title>CCK Example</title>
</head>
<body>
<form target="yCredWindow" action="http://developer.apps.yahoo.com/projects/createconsumerkey" method="post" id="extAuthForm" name="extAuthForm">
<h2>Inputs</h2>
<p>* = Required</p>
<table>
<tr><th>Field</th>
<th>Input</th></tr>
<tr><td>* Application Name: </td>
<td><input name="name" id="name" value="Janrain Engage"></td></tr>
<tr><td>Description: </td>
<td><input name="description" id="desc"></td></tr>
<tr><td>appid: </td>
<td><input name="appid" id="appid"></td></tr>
<tr><td>Return to: </td>
<td><input name="return_to" id="return_to"></td></tr>
<tr><td>* Third Party Name: </td>
<td><input name="third_party" id="third_party" value="Janrain"></td></tr>
<tr><td>* Scopes: </td>
<td><input name="scopes" id="scope" value="ysrw"></td></tr>
<tr><td>Favicon URL: </td>
<td><input name="favicon" id="favicon"></td></tr>
<tr><td>Application URL: </td>
<td><input name="application_url" id="application_url"></td></tr>
<tr><td>* Domain: </td>
<td><input name="domain" id="domain" value="www.janrain.com"></td></tr></table>
<input type="hidden" name="debug" id="debug" value="true">
<button type="reset">clear all fields</button>
<button type="button" id="submitWithDebug">pop window with debug</button>
</form>
<h6>Note: A URL that starts with http:// is required for: Return to, Favicon URL and Application URL. However, you will get an error if you include http:// for the Domain.</h6>
<h2>Returns</h2>
<table>
<tr><td>Key returned:</td>
<td><input type="text" id="cKeyInputField"></td></tr>
<tr><td>Secret returned:</td>
<td><input type="text" id="cSecretInputField"></td></tr>
<tr><td>Appid returned:</td>
<td><input type="text" id="returnAppid"></td></tr></table>
<script src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>
<script>
var formTarget = null;
// used by return_to.html to set the fields with the data that comes back
var setFields = function(id, val) { document.getElementById(id).value = val; };
// pops the window, then submits to it
var popWindowOnSubmit = function(e) {
window.open('', formTarget, 'status=0,toolbar=0,location=0,menubar=0,width=545,height=650');
document.extAuthForm.submit();
};
// handle submit when the button is clicked
YUI().use('node', function(Y) {
formObject = Y.one('#extAuthForm');
formTarget = formObject.getAttribute('target');
Y.on('click', popWindowOnSubmit, '#submitWithDebug');
});
</script>
</body>
</html>
As of august 2017, the only way to get the Email address is to use the scope called Profiles - Read/Write Public and Private. A very stupid choice of misleading options by Yahoo, since we don't want to "write" anything at all.
As a bonus headache, this will also return a list of all emails associated with the account, not just the main one. And there's no way to accurately identify which is the real one - the primary=true field returned in the list cannot be trusted.
You have to add the "Mail Read-Only" scope when you're creating/configuring the app on https://developer.yahoo.com/apps/.
Unfortunately, when I just tried to do that on a newly created app, the option wasn't available.
You may have to get in touch with Yahoo to have them allow you to request these scopes.
you have to add scope=openid while hitting authorization endpoint,
then after obtaining the token after hittng token endpoint,
hit profile endpoint with the obtained access token,
then we get emails under profile json object
In order for you to see the mail checkboxes in the list of potential scopes, Yahoo have to white-list your developer account. I could not find any documentation about this, or instructions for how to ask for it, so I can't back this up with any documentation.
I have found another way to create an app with the Mail API permissions enabled. I noticed if you include an 'api' parameter in the URL you can specify which scopes you want to include regardless of whether they are checked at the bottom. I noticed if you provided 'api=mail' in the URL it defaults to include Mail permissions. So to create a new app with Mail permissions use this URL:
https://developer.yahoo.com/apps/create/?api=mail

How to fix Meteor being unreliable on mobile

I'm not even sure where to start. I have a relatively simple meteor app (http://www.vertexshaderart.com). It's using iron router for routes. The main route / seems like a pretty normal situation. Show the 8 newest posts. Show the 8 most liked posts sort: {likes: -1}.
When I try to view on my phone it only works about 1 out 5 times, maybe less. The site shows up, the main template is clearly rendered and at least one child rendered but the templates waiting for data never show up. They have {{#if Template.subscriptionsReady}} wrappers. Or rather the parts inside the wrapper never show up. I'm guessing the subscriptions never complete on mobile for some reason. In fact the entire 10+ minutes I've been typing and editing this response I've had my phone sitting beside my computer trying to load the page. It's been sitting there loading for > 10 mins, the data spinner in the iOS status bar spinning constantly.
But, when I try to debug it it always works (or at least so far). It works fine in the iPhone Simulator. It works fine if I connect directly to my dev machine over WiFi. Like I said it works fine 1 or of 5 times or so on mobile. I've tried connecting to a debugger USB and then remote debug Safari but it always seems to work when I do that.
You might think it's a bad mobile connection but every other site I view seems to work just fine. Slashdot, Ars, Hackernews, GMail (the website), Facebook's website (not app), Reddit. Etc.
Any idea how I can debug this? Or is this a known issue?
Here's my code
Router.route('/', {
template: 'front',
});
-
<template name="front">
<header>
<div>
<div class="buttons">
{{> userinfosignin}}
</div>
{{> logo}}
</div>
</header>
<div class="container">
<div class="gallery">
{{> artselection sort="newest" limit="8"}}
{{> artselection sort="popular" limit="8"}}
</div>
</div>
<template name="artselection">
<div class="sortcriteria">
<div class="title">
<div>{{sort}}:</div><div class="right"> see all</div>
</div>
<div class="artgrid">
{{#if Template.subscriptionsReady}}
{{#each art}}
{{> artpiece}}
{{/each}}
{{/if}}
</div>
</div>
</template>
<template name="artpiece">
<div class="artpiece">
<a href="/art/{{_id}}">
<img class="thumbnail" src="{{screenshotLink.url}}" />
</a>
<div class="galleryinfo">
<div class="galleryname">
“{{name}}”
by: {{username}}
</div>
<div>
<a href="/art/{{_id}}">
<span class="views">{{views}}</span><span class="likes">{{likes}}</span>
</a>
</div>
</div>
</div>
</template>
I can see all of that gets rendered except the part inside the {{if Template.subscriptionsReady}}
Here's the code for that template
// in a client section
Template.artselection.onCreated(function() {
var instance = this;
instance.autorun(function() {
var sort = getSortingType(instance.data.sort);
instance.subscribe('artSelection', sort, parseInt(instance.data.limit));
});
});
Template.artselection.helpers({
art: function() {
var instance = Template.instance();
var sortField = getSortingType(instance.data.sort);
var sort = {};
sort[sortField] = -1;
var options = {
sort: sort,
limit: parseInt(instance.data.limit),
};
return Art.find({}, options);
},
});
// in a sever section
Meteor.publish("artSelection", function(sortField, limit) {
var find = {
private: {$ne: true},
};
var sort = {};
sort[sortField] = -1;
var options = {
fields: {settings: false},
sort: sort,
limit: limit,
};
return Art.find(find, options);
});
function getSortingType(sort) {
switch (sort) {
case "mostviewed":
return "views";
case "newest":
return "modifiedAt";
case "popular":
default:
return "likes";
}
}
Note: Art is a collection that's pretty much the same as Posts in any tutorial. The data is small. Just _id, username, owner, title, createdAt, modifiedAt, likes, views, hasSound. That's about it and one field settings which is a string which is at most 2-3k but I'm excluding that field in the publish method. In fact, checking the frames in the Chrome debugger when viewing on desktop it looks like only about 12k of data is sent down over the websocket before the front page is completely rendered. In other words, this isn't an issue of sending lots of data.
I'm on Meteor 1.2.1.
Update
I figured out the issue is actually Chrome's Data Saver feature. I made the bad assumption that since both are WebKit under the hood that remote debugging on Safari would help me find the issue but Chrome is doing fancy networking behind the scenes of it's embedded WebKit view. Turning off the data saver feature and it started working.
According to Google you can disable the data saver feature on the server side by adding the header
Cache-Control: no-transform
So for now I'll try adding that header to my site. Otherwise I'm pretty sure google wants it to just work so I've filed a bug
I am absolutely not sure that it will solve your problem, but have you try the "waitOn" feature of iron router (just to help you to locate the problem) ?
Apparently, you would like to be sure that your subscription to your data has been fully established with this block:
{{#if Template.subscriptionsReady}}
{{#each art}}
{{> artpiece}}
{{/each}}
{{/if}}
Could your try to create a route pointing to your template having the issue, and check if the data are loading on this route ?
Something like the following code and see if the problem persists ?
Router.route('/art_selection', {
name: 'artselection',
waitOn: function () { return Meteor.subscribe('artSelection'); },
data: function () {
return {
art: Art.find(),
}
}
});
If it is working well on the route and not on your main page, then I guess your template is not waiting your subscription to be ready the first time it renders, and do not re-render after the subscription has been completed.

How to use NSUserDefaults in phonegap?

I am new to this iOS/phonegap technology.
I am working on an iPhone/iOS app using phonegap. It has a login page with two text fields "Username" & "Password".
<input type="text" class="form-control input-lg user_name" id="txtUserName" placeholder="Username" />
<input type="password" class="form-control input-lg pass_word" id="txtPassword" placeholder="Password" />
<button id="btnLogin" class="large color blue button login_top btn-block" type="submit" value="Login">Login</button>
On $(document).ready(function() Login processing is carried out.
Now I want to save email address of the user. i.e When I logged out it should remember the email address so it doesn't have to be input again.
I am developing this using phonegap. I went through many links and found out that this can be done using
1. NSUserDefaults
2. KeyChain
I am thinking of using NSUserDefaults, but am not understanding how to implement this thing.
i.e Since this is native c code we have to write in the appDelegate.m file. Am I right?
And then how to link this code to my login page?
Can anyone please send me the full code to implement this functionality.
I mean the code that i need to add in appdelegate and linking that code to my login page.
If you or someone else needs it,
There is a cordova plugin for that:
https://github.com/apla/me.apla.cordova.app-preferences/
cordova plugin add me.apla.cordova.app-preferences
Example from it's site:
var prefs = plugins.appPreferences;
// store key => value pair
prefs.store (ok, fail, 'key', 'value');
// store key => value pair in dict (see notes)
prefs.store (ok, fail, 'dict', 'key', 'value');
// fetch value by key (value will be delivered through "ok" callback)
prefs.fetch (ok, fail, 'key');
// fetch value by key from dict (see notes)
prefs.fetch (ok, fail, 'dict', 'key');

How do you post form submissions to a Google Drive Spreadsheet using Google App Scripts

I want to create a form on my site that when a user submits, it posts their data to a particular Spreadsheet in my Google Drive. How can I do this with Google App Scripts?
sample form
<form method='post' action='https://script.google.com/macros/s/xxxx.....'>
Favorite Color <input type='text' value='' name='color' />
Favorite Ice Cream Flavor <input type='text' value='' name='flavor' />
<input type='button' value='submit' />
</form>
so that when I hit submit it creates a record in a Google Drive Spreadsheet
| color | flavor |
red vanilla
Is this doable with GAS, or is sort of task more suited for the Google Drive SDK (via Javascript)?
UPDATE
Used the example from How to add form elements to UI App Service to complete the script
This is the current script I've thrown together... and it works!!!
var SPREADSHEET_ID = '0Aqa6DbU_0sv7dGNrMEEybjNrdm00MlpwTTNx...';
function doPost(e) {
var app = UiApp.getActiveApplication();
SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName('RequestInvites').appendRow([e.parameter.emailAddress, 'hash123']);
app.add(app.createLabel("Form submitted. Your email address is: '" + e.parameter.emailAddress));
return app;
}
function createForm(e){
var app = UiApp.createApplication();
var form = app.createFormPanel();
var flow = app.createFlowPanel();
flow.add(app.createLabel('Enter your email address to get an invitation').setId('inviteLabel'));
flow.add(app.createTextBox().setId('emailAddress').setName('emailAddress'));
flow.add(app.createSubmitButton("Request Invite"));
form.add(flow);
app.add(form);
return app;
}
You can do that with GAS. In your script, use function doPost(e) to retrieve user inputs when the submit button (that you might have forgotten ;) is cliked.
In the doPost function, you can access inputs with their 'name' attribute like that : e.parameter.color and e.parameter.flavor.
Then, you can use Spreadsheet service to write in your spreadsheet. Documentation for this service is here. So you open your spreadsheet, and add a row in the correct sheet like that : SpreadsheetApp.openById('id of your spreadsheet').getSheetByName('colors_and_flavors').appendRow([e.parameter.color, e.parameter.flavor]);.
Let's recap :
function doPost(e) {
SpreadsheetApp.openById('id of your spreadsheet').getSheetByName('colors_and_flavors').appendRow([e.parameter.color, e.parameter.flavor]);
}
Hope it helps ! ;)

Twitter Timeline through Expression Engine

Can anyone help me integrate Twitter through Expression Engine. I am new to expression engine and I have tried to follow the example the Twitter Timeline developed by the EE team but couldn't get it working.
Can anyone help me with step by step process in EE2?
Thanks
Using the example from the Twitter Timeline Plugin download page, insert the following code into one of your ExpressionEngine templates:
{exp:twitter_timeline screen_name="ladygaga" limit="3"}
<div class="tweet">
<div class="date">{created_at format="%m-%d %g:%i"}</div>
<div class="author">
<div class="icon">
<img src="{profile_image_url}" width="48" height="48" alt="" />
</div>
{name}
</div>
<div class="status">{text}</div>
</div>
{/exp:twitter_timeline}
Note: The plugin only works on public Twitter feeds, so make sure that the feed your trying to display is not private. For this example, I'm using Lady Gaga's twitter stream.
All error messages are logged in the Template Parsing Log.
Therefore if you have no output, or unexpected output, enable the Template Parsing Log in the Control Panel's Output and Debugging Preferences at: CP Home > Admin > System Administration > Output and Debugging.
Reload the page in your browser and look through the Template Parsing Log for information from the Twitter Timeline:
If you still can't get the Twitter Timeline plugin to work, post a description of your problem to the ExpressionEngine 2 Technical Support Forum — they'll be able to better help troubleshoot your issue.

Resources