Skip to content

Instantly share code, notes, and snippets.

@mneil
Last active August 29, 2015 14:08
Show Gist options
  • Save mneil/d34885206e4c8cc7a7a7 to your computer and use it in GitHub Desktop.
Save mneil/d34885206e4c8cc7a7a7 to your computer and use it in GitHub Desktop.
Validate Muut Federated Identity Embed
;(function(window){
function sha1(e){var t=function(e,t){var n=e<<t|e>>>32-t;return n};var n=function(e){var t="";var n;var r;for(n=7;n>=0;n--){r=e>>>n*4&15;t+=r.toString(16)}return t};var r;var i,s;var o=new Array(80);var u=1732584193;var a=4023233417;var f=2562383102;var l=271733878;var c=3285377520;var h,p,d,v,m;var g;e=Base64._utf8_encode(e);var y=e.length;var b=[];for(i=0;i<y-3;i+=4){s=e.charCodeAt(i)<<24|e.charCodeAt(i+1)<<16|e.charCodeAt(i+2)<<8|e.charCodeAt(i+3);b.push(s)}switch(y%4){case 0:i=2147483648;break;case 1:i=e.charCodeAt(y-1)<<24|8388608;break;case 2:i=e.charCodeAt(y-2)<<24|e.charCodeAt(y-1)<<16|32768;break;case 3:i=e.charCodeAt(y-3)<<24|e.charCodeAt(y-2)<<16|e.charCodeAt(y-1)<<8|128;break}b.push(i);while(b.length%16!=14){b.push(0)}b.push(y>>>29);b.push(y<<3&4294967295);for(r=0;r<b.length;r+=16){for(i=0;i<16;i++){o[i]=b[r+i]}for(i=16;i<=79;i++){o[i]=t(o[i-3]^o[i-8]^o[i-14]^o[i-16],1)}h=u;p=a;d=f;v=l;m=c;for(i=0;i<=19;i++){g=t(h,5)+(p&d|~p&v)+m+o[i]+1518500249&4294967295;m=v;v=d;d=t(p,30);p=h;h=g}for(i=20;i<=39;i++){g=t(h,5)+(p^d^v)+m+o[i]+1859775393&4294967295;m=v;v=d;d=t(p,30);p=h;h=g}for(i=40;i<=59;i++){g=t(h,5)+(p&d|p&v|d&v)+m+o[i]+2400959708&4294967295;m=v;v=d;d=t(p,30);p=h;h=g}for(i=60;i<=79;i++){g=t(h,5)+(p^d^v)+m+o[i]+3395469782&4294967295;m=v;v=d;d=t(p,30);p=h;h=g}u=u+h&4294967295;a=a+p&4294967295;f=f+d&4294967295;l=l+v&4294967295;c=c+m&4294967295}g=n(u)+n(a)+n(f)+n(l)+n(c);return g.toLowerCase()}
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};
var example_api = 'EX: ' +JSON.stringify({api: {
key: '6dffSnhECs',
signature: '231a3ccf3aef9fc718e97f3989ce3ea2bb24cb7d',
message: '{user{}}',
timestamp: Date.now()
}});
var _message = Base64.encode(JSON.stringify({user:{}}));
var _now = Date.now();
var _signature = function(secret){
return sha1(secret + ' ' + _message + ' ' + _now);
};
function _muutCssExists() {
var ss = document.styleSheets;
for (var i = 0, max = ss.length; i < max; i++) {
if (/m(oo)t\.css/i.test(ss[i].href))
return true;
}
return false;
}
var real_api = function(secret, key, m){
if( !secret )
return example_api;
var obj = {api: {
key: key,
signature: _signature(secret),
message: _message,
timestamp: _now
}};
if( m ){
for( var prop in m ){
obj[prop] = m[prop];
}
}
return JSON.stringify(obj);
};
var init = function(){
muut(function(app){
app.on('load', function(){
var c = app.conf(),
s = app.secretkey;
if( !c.hasOwnProperty('api') ){
console.log('Missing api', example_api);
return;
}
if( !c.api.hasOwnProperty('key')){
console.log('Missing api', example_api);
}
var k = c.api.key;
if( !c.api.hasOwnProperty('signature')){
console.log('Missing signature', real_api(s, k));
}
if( !c.api.hasOwnProperty('message')){
console.log('Missing message', real_api(s, k));
}
if( !c.api.hasOwnProperty('timestamp')) {
console.log('Missing timestamp', real_api(s, k));
}
if( c.api.hasOwnProperty('login_url')) {
console.log('Login URL goes outside the api object', real_api(s, k, {login_url : c.api.login_url}));
}
var sig = sha1(s + ' ' + c.api.message + ' ' + c.api.timestamp);
if( c.api.signature !== sig ){
console.log('Your signature should be ', sig);
}
if(c.api.timestamp > _now / 1000){
console.log('your time is in the future', new Date(c.api.timestamp*1000));
}
if(c.api.timestamp < Math.floor(_now / 1000) - 100){
console.log('your time is too old', new Date(c.api.timestamp*1000));
}
var m = JSON.parse( Base64.decode(c.api.message) );
if(!m.hasOwnProperty('user') ){
console.log('User object must exist in the message', 'base64.encode({user:{}})', 'for anonymous users');
return;
}
if(!m.user.hasOwnProperty('id')){
console.log("id is required", m);
}
if(!m.user.hasOwnProperty('displayname')){
console.log("displayname is required", m);
}
if( !_muutCssExists() ){
console.log('Missing Muut CSS. Paste in head:', '<link rel="stylesheet" href="https://cdn.muut.com/1/moot.css" />')
}
});
});
};
if (window.addEventListener) {
window.addEventListener("load", init);
}
else {
window.onload = init;
}
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment