Add URL parameters in Google Script Web apps - javascript

Tried hours on this one now - is there any way to add a parameter to the URL on server side Google Script in a deployed web app, that is open for anyone (not only Google accounts)?
I want to store a key for when a user is logged in, so that the user doesn't have to log in again each time the browser is refreshed.. Say my current url is:
https://script.google.com/a/macros.../exec
Can I in some way add in a GAS function at login so that the URL gets modified to something like
https://script.google.com/a/macros.../exec?key=abcdef&name=John%20Doe
So that if the doGet(e) function runs again (website reloaded) and if the temporary generated key matches the username in my database, the user will be directed to page B, and if the key doesn't match (or have been deleted on a time trigger) the user will be directed to page A (the login page)?
I also tried to find ways of putting something in the local cache but can't figure that out either.. Google CacheService seem to only store keys on me as a user and not client side.
Example of what I want to achieve:
function doGet(e){
var name = e.parameter.name, output;
if(name === undefined){
/*/
Add parameter name=john to URL..
obviously what I intend to is to create a HtmlOutput on a login-page
and then in a later (function login()) add this parameter there and not
here, but if anyone can work this out for me I got the solution
/*/
} else {
output = HtmlService.createHtmlOutput('Welcome back ' + name);
}
return output;
}

Here is a possible solution that saves usernames to the PropertiesService based on the URL parameters provided, and if already exists, gets the key.
function doGet(e) {
//use the session service to get the active users email
var currentUser = e.parameter.name;
var key = e.parameter.key;
var props = PropertiesService.getUserProperties().getProperty(currentUser);
if(props) {
//do something with the key
} else {
//if there is no username key in the properties service, then add it
PropertiesService.getUserProperties().setProperty(currentUser, key);
}
}
Here are the docs:
https://developers.google.com/apps-script/reference/properties/properties-service#getUserProperties()

Related

Auth0 unable to get ID token / user metadata

I am currently working on adding Auth0 to a Vue.js/Node.js application and so far I have figured out how to allow users to register and log in (to /callback) and that seems to be working fine. However, I have manually added (will be automatic later on) some data to the user metadata section. I have the below code as a rule that is turned on. I can’t seem to get access to the data on the Vue.js end of things. What I’d like is to be able to get the user data and user metadata so I can store it in my front end.
Rule code
function (user, context, callback) {
const namespace = 'account_signup_type/';
const namespace2 = 'account_type';
context.idToken[namespace + 'is_new'] = (context.stats.loginsCount === 1);
context.idToken[namespace2] = user.account_type;
context.idToken.user = user;
callback(null, user, context);
}
Code I am trying in my Vue.js front end
getIdTokenClaims(o) {
return this.auth0Client.getIdTokenClaims(o);
}
Currently, this returns undefined
I ended up figuring it out, there was no namespace being created in the id_token which resulted in it not properly passing the data through to the Vue .js app. I added a namespace using a web address format with the domain extension cut off and it now works.

How to display internal User ID instead of Client ID (ga cookie), in Google Analytics via GTM?

I have surfaced my system's user id to display as a JS variable. I created a Custom Dimension to pull that user id, and connect it to the client id provided by Google.
Here's the dimension's code...
function() {
try {
var tracker = ga.getAll()[0];
return tracker.get('clientId');
} catch(e) {
console.log("Error fetching ID");
return "Customer ID N/A";
}
}
The variable that displays our User ID is ECID. I've tried every which way I can think of, but the only thing that works is what's above. I don't want the cookie id. I want to be able to display our internal User ID.
Here's how the event fires...
I have no idea what I'm doing wrong, but the goal is to have something like this (pulled from a YT video)...
While creating the view you need to enable User_Id reports . Then only it will show user_id instead of client_id

Positively identify the current user from my javascript in SharePoint

When logging into SharePoint a cookie called "AADAuth" is set on ".office.com". The contents of this cookie is a JWT and it positively identifies the current user. If I could get this cookie from my javascript in SharePoint, I could send the JWT to my custom API and with Microsofts public certificate, I would be able to positively verify the identity of the user.
However, since this cookie is on ".office.com" which is obviously not my SharePoint domain, I cannot access that cookie.
So is there a way to get the JWT on SharePoint?
Otherwise, is there any other way I can find any content on the client side javascript to positively identify the current user?
I know I can initiate a new authentication process from my javascript in SharePoint, but that takes time and I'm looking for a solution that doesn't take much time for the end user, so hopefully I can use some of the information already in SharePoint.
I'm going to include a couple of different methods as it seems you may be looking for a specialized solution rather than a general one.
General Solution
I'm going to expand on DevBot's answer using _spPageContextInfo.userId, which is a number, not the person's user name.
<script type="text/javascript">
var spContextUserId;
$(document).ready(function() {
spContextUserId = _spPageContextInfo.userId;
console.log('user context id: ' + spContextUserId);
console.log('Executing sp.js...');
SP.SOD.executeOrDelayUntilScriptLoaded(loadSPUserProfiles, 'sp.js');
});
function loadSPUserProfiles() {
// ..wait for sp.js to load
console.log('sp.js loaded. Loading sp.userprofiles.js...');
SP.SOD.executeOrDelayUntilScriptLoaded(getUserProperties, 'SP.UserProfiles.js');
}
</script>
<script type="text/ecmascript">
var userProfileProperties;
function getUserProperties() {
try {
console.log('sp.userprofiles.js loaded...');
console.log('Getting user properties...');
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
userProfileProperties = peopleManager.getMyProperties();
clientContext.load(userProfileProperties);
clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
}
catch (err) {
console.log(err.message);
}
}
function onRequestSuccess() {
console.log('in request success routine');
var accountName = "";
try {
//console.log(userProfileProperties);
//accountName = userProfileProperties.get_accountName; // also works
accountName = userProfileProperties.get_userProfileProperties()['AccountName'];
console.log('accountName from svc: ' + accountName);
// Now see if that account name matches the ID
getUserInfo(accountName, function(userInfo){
console.log('User Id: ' + userInfo.ID);
if (spContextUserId == userInfo.ID) {
alert('Verified');
} else {
alert('Not verified.');
}
},
function(sender,args){
console.log(args.get_message());
});
catch(ex) {
console.log(ex.message);
}
function getUserInfo(userName, Success, Error)
{
var context = new SP.ClientContext.get_current();
var userInfoList = context.get_web().get_siteUserInfoList();
var query = new SP.CamlQuery();
var viewXml = "<View> \
<Query> \
<Where> \
<Eq><FieldRef Name='UserName' /><Value Type='Text'>" + userName + "</Value></Eq> \
</Where> \
</Query> \
<RowLimit>1</RowLimit> \
</View>";
query.set_viewXml(viewXml);
var items = userInfoList.getItems(query);
context.load(items,'Include(Deleted,Department,EMail,FirstName,ID,IsActive,IsSiteAdmin,JobTitle,LastName,MobilePhone,Name,Notes,Office,Picture,SipAddress,UserName,WebSite,WorkPhone)');
context.executeQueryAsync(function() {
if(items.get_count() > 0) {
var item = items.itemAt(0);
Success(item.get_fieldValues());
}
else {
Success(null);
}
}, Error);
}
</script>
This getUserInfo function was posted at https://sharepoint.stackexchange.com/questions/31457/get-user-via-javascript-client-object-model , but I've used a similar construct, myself.
This takes the numeric ID assigned to a user by the page context and compares this against the People Manager version after getting the current web context. To me, this is about as effective as you're going to get using just the JSOM to verify that a user matches their login context, if we assume they are already on a SharePoint page and have been authenticated via Windows, as they should have been.
Tokens
If you are still trying to pursue getting the JWT or using a token method, or just otherwise need access to this path for some reason, say to make an add-in work or because they're accessing SharePoint from outside it, you're going to want to review Microsoft's documentation on what the tokens look like and how to create one, because using Context Token flow requires using the CSOM, not JSOM. There, you have to get a context token to get an access token:
SharePointContextToken contextToken =
TokenHelper.ReadAndValidateContextToken(contextTokenString,
Request.Url.Authority);
string sharePointUrl = WebConfigurationManager.AppSettings.Get("RedirectUri");
Response.Redirect(TokenHelper.GetAppContextTokenRequestUrl(sharePointUrl, Server.UrlEncode(Request.Url.ToString())));
where you have set up the RedirectUri in the web.config:
<configuration>
<appSettings>
<add key="RedirectUri" value="https://contoso.com/RedirectAccept.aspx" />
</appSettings>
<configuration>
Instead, you'd have to translate all of this into a JSOM method to match what you say you're trying to achieve, creating your own using "Authorization flow", and then you should be able to use it against your API.
In the Authorization Code flow, there is no context token, so you cache the refresh token itself, and the user gets a new refresh token each time he or she launches the add-in (https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/handle-security-tokens-in-provider-hosted-low-trust-sharepoint-add-ins#CacheKey). It must redirect the user to the SharePoint's OAuthAuthorize.aspx:
/oauthauthorize.aspx?IsDlg=1&client_id=c78d058c-7f82-44ca-a077-fba855e14d38&scope=list.read&response_type=code&redirect_uri=https%3A%2F%2Fcontoso%2Ecom%2Fredirectaccept.aspx
IsDlg=1 would launch an authentication dialog.
The client_id has to be the same as when your add-in got registered with SharePoint.
Perhaps this would work as a GET inside an AJAX call. Microsoft talks about redirecting the user to this URL, which indicates to me it would be a call to actually change the URL:
window.location.href = 'http://www.mysharepointsite.com/somesite/oauthorize.aspx?...';
My suggestion would be to review this documentation thoroughly and construct what they say you need/perform the redirects required using this information:
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/handle-security-tokens-in-provider-hosted-low-trust-sharepoint-add-ins
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/authorization-code-oauth-flow-for-sharepoint-add-ins
Without more information on how you are accessing SharePoint, and why you think the token method is the only way to verify an account, this is a difficult question to answer as it seems like you may have a specific scenario you are trying to build for, and there's often a lot of trial-and-error involved to ensure all permissions, GUIDs, etc. are registered and accurate.
You can grab _spPageContextInfo.userId or _spPageContextInfo.userLoginName.
More info about that object here.

adding data based on users login credentials (Lightswitch HTML)

I've been doing some research into how I can add data based on the login credentials. as an example scenario lets say I want a user to login to the application and then based on there login, add there hours they have done for that day, so like a timesheet application.
I don't want the user that is logged in to see any other names other
than there own.
the browse screen would show only there times they have submitted
rather than everyones aswell.
when using the insert call method in (_customnameDataService.cs) you can add in a username by associating a field within a table like below:
entity.Username = Application.User.Name
so if this is possible there must be a way of calling this in JavaScript when logging in so any help or pointers would be great help. Adding a DataItem and displaying the username would be most preferable. (using edit render code) then from this I can pass it through the hierarchy and display only the information associated with the logged in user.
follow these steps to achieve the above question:
Google GetUserName.ashx to get the code for this file to add to your
Lightswitch HTML Project.
copy the below function into the javascript file (in my case a Browse screen for my users)
function CallGetUserName(operation) {
$.ajax({
type: 'post',
data: {},
url: '../web/GetUserName.ashx',
success: operation.code(function AjaxSuccess(AjaxResult) {
operation.complete(AjaxResult);
})
});
}
For the users that can login in and access the Lightswitch Application, the user information must be stored somewhere, in my case "tbl_Users". This table has a row called username. Using the below code this enables an administrator or someone high up in the hierarchy to access all the users, and also the specific user referenced in the table to access themselves.
myapp.BrowseUsers.username_postRender = function (element,
contentItem) {
msls.promiseOperation(CallGetUserName).then(function PromiseSuccess(PromiseResult) {
if (PromiseResult == 'TestUser' || PromiseResult == 'administrator') {
} else {
contentItem.value = PromiseResult;
}
});
};
What is actually happening?
The function is calling the GetUserName.ashx file, which in turn retrieves the current user logged in. (from the aspnet_Users table which is automatically created) I have used a foreign key to associated my table (tbl_Users) and aspnet_Users together.
in the debug or release environment if you were to add a data item (string) and display this information, it would return ("TestUser")
myapp.BrowseUsers.displayUsername_postRender = function (element,
contentItem) {
msls.promiseOperation(CallGetUserName).then(function PromiseSuccess(PromiseResult)
{
element.innerText = PromiseResult;
}); };

Can I detect valid JSONP return?

I want to send/receive data to a web service on a different server that does not have CORS enabled. I have to use JSONP to do it. The service requires authentication and most of the time the user is in an SSO environment and the SSO mechnaism easily passes them to the service without issue.
When not inside the SSO environment, the user is redirected (301) to a login page, which of course returns invalid javascript because the file would start with <!Doctype...
Is there a way to see if the returned data is operable? I know exactly what the first 15 chars should be anytime the user can successfully access the service. I would like to check the return and then do something like:
if(dataIsValid){ //continue normally, build page with returned data }
else{ //redirect to non-SSO login page }
Or anything that resembles that kind of a workflow.
I assume you're using jQuery since you've added a relevant tag.
var dataIsValid = true;
var data = {};
try {
data= $.parseJSON(data);
} catch (exc){
dataIsValid = false;
}
//...

Categories

Resources