I want to create a sas token for registration of device in Azure IoT hub,using postman.The sas token will be created with pre-requested script.
var resourceUri = "scopeId/registrations/deviceId" // The resource uri
var deviceId = "deviceId";
resourceUri = encodeURIComponent(resourceUri.toLowerCase()); // Encode the url
var expires = Math.ceil((Date.now() / 1000) + 10 * 60); // Expire the token 60 minutes from now
var toSign = resourceUri + "\n" + expires; // this is the string format to gen signature from
var crypted = CryptoJS.HmacSHA256(deviceId, CryptoJS.enc.Base64.parse("symmetrickKeyOfEnrollmentGroup"));
var signature = CryptoJS.HmacSHA256(toSign, crypted); // The signature generated from the decodedKey
var encodedUri = encodeURIComponent(CryptoJS.enc.Base64.stringify(signature)); // The url encoded version of the Base64 signature
// Construct authorization string (shared access signature)
var iotHubSasToken = "SharedAccessSignature sr=" + resourceUri + "&sig=" + encodedUri + "&se=" + expires +"&skn=registration";
console.log(iotHubSasToken);
postman.setGlobalVariable("token", iotHubSasToken);
This is what i created, but i receive Unauthorized.Some ideas where i am wrong, i think i somewhere in the signature, because the "sr" and "se" are okay
Output of the code above which throws Unauthorized:
SharedAccessSignature sr=0ne002ee24e%2Fregistrations%2Fcxdlx3f3zv9xx3f3zq&sig=Ukz%2FPyyLaweLYmFq4gHUP%2BhiO7X%2FyQAE9noAaw4nuLU%3D&se=1659940252&skn=registration
References:
About SAS: https://learn.microsoft.com/en-us/azure/iot-dps/how-to-control-access
About the REST API: https://learn.microsoft.com/en-us/rest/api/iot-dps/device/runtime-registration/register-device#provisioningserviceerrordetails
About DPS sas token: https://learn.microsoft.com/en-us/azure/iot-dps/how-to-control-access
Error:
The issue was in the signature.
var crypted = CryptoJS.HmacSHA256(deviceId, CryptoJS.enc.Base64.parse("symmetrickKeyOfEnrollmentGroup"));
var signature = CryptoJS.HmacSHA256(toSign, crypted); // The signature generated from the decodedKey
var encodedUri = encodeURIComponent(CryptoJS.enc.Base64.stringify(signature)); // The url encoded version of the Base64 signature
This is the right way of creating it.
Related
I'm using ASP.Net Core Identity to store user info in JWT Token. I found that there is a problem with decoding the token that consists of Url Photo from Facebook.
Here is the way I'm decoding the token with javascript:
JSON.parse(atob(token.split('.')[1]));
and it results in the following error:
Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
Referring to this post I think that there must be some replacement in the back-end with C# on the photo URL. I applied the changes but it wasn't useful.
Here is the URL I got from Facebook:
https://scontent-ams4-1.xx.fbcdn.net/v/t1.30497-1/84628273_176159830277856_972693363922829312_n.jpg?stp=c15.0.50.50a_cp0_dst-jpg_p50x50&_nc_cat=1&ccb=1-7&_nc_sid=12b3be&_nc_ohc=D3l7nXsZ3NgAX_SAb-s&_nc_ht=scontent-ams4-1.xx&edm=AP4hL3IEAAAA&oh=00_AT8ViyxqwFycpp5TQRkSMoM34pivsmHOhPZSVJfrdYMRdw&oe=62C47219
JSFiddle Example
UPDATE:
Create a token that include photo Url received from Facebook.
public async Task<DtoAuthenticationResult> CreateTokenAsync(AppUser user)
{
var claims = new List<Claim>
{
new ("UserName", user.UserName),
new ("PhotoUrl", user.ProfilePhotoUrl),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
var roles = await _userManager.GetRolesAsync(user);
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
var cred = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
//Expires = DateTime.Now.Add(_jwtSettings.TokenLifeTime),
Expires = DateTime.UtcNow.AddSeconds(120),
SigningCredentials = cred
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return new DtoAuthenticationResult
{
Success = true,
Token = tokenHandler.WriteToken(token)
};
}
client-side:
export class UserToken {
token: string;
success: string;
errors: string[];
}
facebookAuth(model: SocialUser) {
return this.http.post(this.baseUrl + 'account/facebookAuth', model)
.pipe(map((response: UserToken) => {
const user = response;
this.setCurrentUser(response);
}));
}
setCurrentUser(authResult: UserToken) {
const user: User = this.getDecodedToken(authResult.token);
...
}
getDecodedToken(token: string) : User {
let u = JSON.parse(atob(token.split('.')[1]));
let usr = new User();
...
}
Update 2:
Token value :
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6Ik5pY2suZnVyeWZjYkBnbWFpbC5jb20iLCJJZCI6IjIwMCIsIlVzZXJOYW1lIjoiTmljayIsIlNleCI6IjAiLCJHZW5kZXIiOiIwIiwiUGhvdG9VcmwiOiJodHRwczovL3Njb250ZW50LWFtczQtMS54eC5mYmNkbi5uZXQvdi90MS4zMDQ5Ny0xLzg0NjI4MjczXzE3NjE1OTgzMDI3Nzg1Nl85NzI2OTMzNjM5MjI4MjkzMTJfbi5qcGc_c3RwPWMxNS4wLjUwLjUwYV9jcDBfZHN0LWpwZ19wNTB4NTAmX25jX2NhdD0xJmNjYj0xLTcmX25jX3NpZD0xMmIzYmUmX25jX29oYz1EM2w3blhzWjNOZ0FYX1NBYi1zJl9uY19odD1zY29udGVudC1hbXM0LTEueHgmZWRtPUFQNGhMM0lFQUFBQSZvaD0wMF9BVDhWaXl4cXdGeWNwcDVUUVJrU01vTTM0cGl2c21IT2hQWlNWSmZyZFlNUmR3Jm9lPTYyQzQ3MjE5IiwianRpIjoiZTFkMGZkZjktMjg2MS00NzUxLWJlY2ItYzM1MjRhZDY0YWEzIiwibmJmIjoxNjU0Njk2MDA0LCJleHAiOjE2NTQ2OTYxMjQsImlhdCI6MTY1NDY5NjAwNH0.MZRvz57yjCmtkZyCDfGu3RX2LZ3KglnMM3ZzTFE73Ln7TrPyQ5_EgeWr2w0fBLOIObN6KSs9Bwvcoya7gSf7Kg
You need to convert base64url encoding to the usual base64 first. Please Try this code:
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
console.log(JSON.parse(jsonPayload));
https://jsfiddle.net/ukmr6vjd/
I'm working with ARIS tool and I want to make calls(GET, POST...) in ARIS to ARIS API repository!
I have authentication that works when I try it directly in the repository, but I got an error when I debug the code I have in ARIS.
The error: Error running script: Connection refused: connect.
I have the following code:
var obj = new java.net.URL(url);
var con = obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", java.net.USER_AGENT);
var tenant = "";
var name = "";
var password = "";
var key = "";
var authString = tenant + ":" + name + ":" + password + ":" + key;
var encoder = new java.lang.String(Base64.encode(authString));
con.setRequestProperty("Authorization", "Basic" + encoder);
var responseCode = con.getResponseCode();
var iN = new java.io.BufferedReader(new java.io.InputStreamReader(con.getInputStream()));
var inputLine = new java.lang.String();
var response = new java.lang.StringBuffer();
while((inputLine = iN.readLine()) != null){
response.append(inputLine);
}
iN.close();
return new java.lang.String(response);
Is the problem that I use Basic authentication, but I have tenant and key also or it's something else?
Also, name, password, key and tenant I'm leaving empty for security purposes, but in the original code the values are inserted. Also the url parameter contains the url link that is called directly in the repository.
Can someone please help me?
Thanks!
any thoughts as to why this script emails an attachment but the attachment is not the correct spreadsheet, and looks like some sort of google error page.
function getGoogleSpreadsheetAsExcel(){
try {
var ss = SpreadsheetApp.getActive();
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + ss.getId() + "&exportFormat=xlsx";
Logger.log(url);
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName() + ".xlsx");
MailApp.sendEmail("youremail#email.com", "Google Sheet to Excel", "The XLSX file is attached", {attachments: [blob]});
} catch (f) {
Logger.log(f.toString());
}
}
I guess API has changed. You can try Drive REST API(v3) instead. Replace
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + ss.getId() + "&exportFormat=xlsx";
var params = { ... };
var blob = UrlFetchApp.fetch(url, params).getBlob();
to
var url = "https://www.googleapis.com/drive/v3/files/" + ss.getId() +
"/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&key=" +
"{your API key}";
var blob = UrlFetchApp.fetch(url).getBlob();
I tested and it worked. Of course you first should get your own API key, etc, at API Manager. Then you can try some APIs like simple GET requests at APIs Explorer. Or you can try some APIs, in this case Files: export, also at the documentation page itself, but notice that you cannot try your own API key here.
This is the updated code that #sangbok helped with:
function getGoogleSpreadsheetAsExcel(){
try {
var ss = SpreadsheetApp.getActive();
var sheet = DriveApp.getFileById(ss.getId());
// sets sharing to public - to send out email.
sheet.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT);
var url = "https://www.googleapis.com/drive/v3/files/" + ss.getId() + "/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&key=" + "YOURAPIKEYGOESHERE4";
var blob = UrlFetchApp.fetch(url).getBlob();
Logger.log(url);
blob.setName(ss.getName() + ".xlsx");
var now = new Date();
MailApp.sendEmail("YOUREMAILADDRESSGOESHERE", "EMAIL SUBJECT " + now , "EMAIL BODY " + now , {attachments: [blob]});
} catch (f) {
Logger.log(f.toString());
}
// returns the file back to Private access
sheet.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.EDIT);
}
I'm trying to add a user who clicks on a button in a SharePoint (online) site to a Office 365 group. I know this can be done via JSON using the Add Member API.
https://github.com/OfficeDev/microsoft-graph-docs/blob/master/api-reference/v1.0/api/group_post_members.md
I am however really inexperienced when it comes to JSON and keep messing up the POST function. This is the code I have currently, everything before the comma has been working fine.
function showButton() {
$('btn-1').on('click', function(event) {
var userProfileProperties
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
userProfileProperties = peopleManager.getMyProperties();
clientContext.load(userProfileProperties);
clientContext.executeQueryAsync(onSuccess, onFail);
function onSuccess(){
accountProperties = userProfileProperties.get_userProfileProperties();
accountId = accountProperties['msOnline-ObjectId'];
//JSON Query
jQuery.ajax({
url: "https://mysite.sharepoint.com/groups/groupID/members/$ref";
method: "POST";
contentType: "application/json";
dataType: 'json',
{
"#odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/" + accountId
};
});
};
function onFail(){
alert(failed);
};
});
};
In your document , you will find authentication token is required in the Request headers .Without authentication token ,you will receive an error as :
"code": "InvalidAuthenticationToken", "message": "Bearer access token is empty."
As a solution , you could try following steps :
1.Register a javascript Application in Azure AD and configure your app to allow the OAuth 2.0 implicit grant flow.Tokens are obtained using the OAuth 2.0 implicit grant flow. Using implicit grant, your application requests an access token from Azure AD for the currently signed-in user by sending the user to an authorization URL where the user signs in with their Office 365 credentials and then is redirected back to the app with the access token in the URL .
2.Add permissions to Graph API .
3.Add an html page to your sharepoint online(using Explorer mode) .
4.Edit the html , write below function to get an access token:
function requestToken() {
// Change clientId and replyUrl to reflect your app's values
// found on the Configure tab in the Azure Management Portal.
// Also change {your_subdomain} to your subdomain for both endpointUrl and resource.
var clientId = '3dadb44e-feaa-4158-90f5-e129e15db66d';//ID of your App in Azure
var replyUrl = 'https://o365e3w15.sharepoint.com/sites/XXX/app.html'; //my sharepoint page that requests
//an oauth 2 authentification and data
//It is also referenced in the REPLY URL field of my App in Azure
var endpointUrl = 'https://graph.microsoft.com/v1.0/me/messages';
var resource = "https://graph.microsoft.com/";
var authServer = 'https://login.windows.net/common/oauth2/authorize?';
//var authServer = 'https://login.microsoftonline.com/common/oauth2/authorize?';//this works either
var responseType = 'token';
var url = authServer +
"response_type=" + encodeURI(responseType) + "&" +
"client_id=" + encodeURI(clientId) + "&" +
"resource=" + encodeURI(resource) + "&" +
"redirect_uri=" + encodeURI(replyUrl);
window.location = url;
}
After that ,you could make an ajax call to graph api endpoint to get/post request, for example, get current user's messages:
var endpointUrl = "https://graph.microsoft.com/v1.0/me/messages";
var xhr = new XMLHttpRequest();
xhr.open("GET", endpointUrl);
var myToken = getToken();
// The APIs require an OAuth access token in the Authorization header, formatted like this:
//'Authorization: Bearer <token>'.
xhr.setRequestHeader("Authorization", "Bearer " + myToken);
// Process the response from the API.
xhr.onload = function () {
if (xhr.status == 200) {
//alert('data received');
var message="";
var object = JSON.parse(xhr.response);
for(i=0;i<object.value.length;i++){
message+='Subject: ' + object.value[i].subject + '<br>';
}
document.getElementById("results").innerHTML = message;
} else { }
}
// Make request.
xhr.send();
display this app.html into any SharePoint Webpart page by calling it within an iframe tag.
All detail steps you will find in this article , i have tested and work fine in my side .
I am receiving a video bytes from a device, and it should be a multipart request. Its a post api which is created in node.js. How can I recieve a multipart request in post api in node.js. Below is the code which is currently saving video bytes.
app.js
app.post('/saveVideo',service.saveVideo);
routes.js(class service method saveVideo)
var video_byte_string = req.param('videoByteStr');
var writeStream = gfs.createWriteStream({mode:'w',content_type: 'video/mov'});
var buffer = new Buffer(video_byte_string).toString('base64');
var response = streamifier.createReadStream(buffer).pipe(writeStream);
You need to append a separator after video bye string like following
if byte string are - 'abcdefghijklmnopqrstuvwxyz';
then you need to append any separator(#####) like this to identify end of complete string
now your request string will be like this - 'abcdefghijklmnopqrstuvwxyz'+'#####';
Now your request string having a end separator(#####) from which you can identify your complete chunks
var video_byte_string = req.param('videoByteStr');
isCorrectString = false;
data_stream += video_byte_string;
var n = data_stream.lastIndexOf("#####");
if (n === -1) {
var steamArr= data_stream.split("#####");
var completeByteString = steamArr[0];
isCorrectString = true;
}
if(isCorrectString) {
var writeStream = gfs.createWriteStream({mode:'w',content_type: 'video/mov'});
var buffer = new Buffer(completeByteString).toString('base64');
var response = streamifier.createReadStream(buffer).pipe(writeStream);
}
Thanks