I want to add Idap authentication to the web applications that I developed with HTML and AngularJS.
But I don't understand how I should do it. I looked online and only found answer to how to set up IDAP in JAVA.
{
String uid = "User";
String password = "Password";
String BASE = "ou=People,dc=objects,dc=com,dc=au";
String userDN = "uid=" + uid + ",ou=people," + BASE;
String HOST = "ldap://ldap.example.com:389";
String INIT_CTX = "com.sun.jndi.ldap.LdapCtxFactory";
// Setup environment for authenticating
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, INIT_CTX);
env.put(Context.PROVIDER_URL, HOST);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userDN);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.REFERRAL, "follow");
try
{
DirContext authContext =
new InitialDirContext(env);
System.out.println("I am authenticated");
}
catch (AuthenticationException ex)
{
System.out.println("authentication failed");
}
catch (NamingException ex)
{
ex.printStackTrace();
}
}
So the above code is just a tryout from me, and it works fine.
I will make it into a function later and i want to use it to authenticate the users that come to use my web application.
I have no idea how to do that though. I mean I know I should create a HTML page that request users to enter ID and Password. then I can use AngularJS to capture those data.
But then what?
How do I use the Java function in AngularJS or HTML? I mean once authenticated, It should jump to the index.html page.
Thanks guys, Sorry i am new to web development.
Java runs on the backend only. You grab the username/password in Angular and POST it back to your Java application. Typically, you'd set this up with Dropwizard or Spring Boot. The backend then returns either success or failure to Angular which then sets the browser location to your index.html.
Read up on Jersey, REST and Dropwizard, there's lots of examples. Alternatively, you can run a Tomcat server and let this do the LDAP auth via container managed security - you only need to supply the LDAP info in the web.xml.
Related
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.
Unfortunately, there are many snippets, but no complete code examples. I'm trying to allow my group's events to be seen in a webpage outside of FB, and following the Javascript SDK example quick start I'm able to put the login and share buttons. But when I try to access my group's events, I get the error - "An access token is required to request this resource." Where do I put the access token in this code?
window.fbAsyncInit = function() {
FB.init({
appId : '{myappID}',
xfbml : true,
version : 'v2.8'
});
FB.AppEvents.logPageView();
FB.api(
'/myGroupID/events',
'GET',
{},
function(response) {
// Insert your code here
}
);
};
A couple of things:
I don't need my users to log in, as my group is public; my events are public. If someone is casually browsing through my website I want them to be able to see the events.
One of the other things that I've had trouble with is extremely short answers. Coming from the .NET community, I'm used to seeing lots of tutorials, and lots of complete code examples for how to do things. There are few "long form" answers or tutorials - even stackoverflow answers (like this one) don't contain enough detail on how to do this stuff. Especially the access token thing.
Is there a complete example of how to do this?
Thanks in advance.
You COULD add the Token like this:
FB.api(
'/myGroupID/events',
'GET',
{access_token: 'xxx'},...
...but that would expose your Token (which is always meant to be kept secret) to everyone visiting the website. You have to do that API call server side. Check out the PHP SDK or just use PHP cURL. The Token is just a GET parameter.
Ok, I figured it out. The point of all of this is to get the Access Token that Facebook says it wants. The Access Token is really the appsecret_proof (and not the access_token - the access_token is a different thing. See later in this post), so be aware of that. I cobbled together some different code examples (like this one, and a super, very careful reading of the Facebook graph api docs, to reach an answer. I coded in C# rather than Javascript because a lot of this needs to be done server side, and I'm more comfortable there anyway.
I created a console app as a proof of concept. A few notes:
the page_id is, in my case, for a group, not a (capital P) Page,
which is a different thing.
The access_token and app_secret are from the app
you've (hopefully) already created. (If you need to get the access_token in the first place, there
are some docs out there to help you get this part started.) You should also
make sure to use (as of .NET 1.0) the dotnet core secret manager
to protect your secrets when you develop so you don't pass them
around via source control.
This last one is big - the appsecret_proof is a combination of your access_token and your app_secret hashed together (with the app_secret being the key) and then made part of the query string. This is what Facebook wants when it says "An access token is required to request this resource."
public static string page_id = {your_page_id};
public static string access_token = {your_app_access_token};
public static string app_secret = {your_app_secret};
public static string appsecret_proof = FaceBookSecret(access_token, app_secret);
static void Main(string[] args)
{
Console.WriteLine("Making API Call...");
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
{
client.BaseAddress = new Uri("https://graph.facebook.com/" + page_id + "/");
HttpResponseMessage response = client.GetAsync("events?access_token=" + access_token + "&appsecret_proof=" + appsecret_proof).Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine("Result: " + result);
}
Console.ReadLine();
}
internal static string FaceBookSecret(string content, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] messageBytes = Encoding.UTF8.GetBytes(content);
byte[] hash;
using (HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes))
{
hash = hmacsha256.ComputeHash(messageBytes);
}
StringBuilder sbHash = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sbHash.Append(hash[i].ToString("x2"));
}
Console.WriteLine(sbHash);
return sbHash.ToString();
}
So after all of this runs, I get a nice json string with all of my events.
I am completely new to the Facebook API. I would like to incorporate Facebook login into my application. I am using the Javascript SDK on the front-end to log the user in and retrieve the user_id and signed_request from Facebook. I then plan to send these two pieces of information via AJAX to my server (either php/hack (hhvm), node, java, or whichever language I can determine is quickest for decoding) every time my logged in user does an action on my application to validate if the user is indeed logged in and is the person they say they are. For me to accomplish this, I need to decode the signed_request, for example in php:
function parse_signed_request($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$secret = "appsecret"; // Use your app secret here
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
which then I will be able to extract the following JSON object:
{
"oauth_token": "{user-access-token}",
"algorithm": "HMAC-SHA256",
"expires": 1291840400,
"issued_at": 1291836800,
"user_id": "218471"
}
to be able to compare if the user_id the user sent over matches the one in the JSON object. Then if it matches I can complete my business logic (DB manipulation).
My big concern here is a user will be sending many requests to my server, so every time I will need to decode this signed_request which can really kill my server performance. I was thinking I maybe could call Facebook from my server, pass the user_id, and receive the signed_request string, which I can then match with the signed_request string the user sent over from the client_side and see if they match. This would be more efficient, but it does not seem Facebook offers anything like this. Is there any other methods besides the heavy performing decoding to validate a user? I have gone through quite a bit of the Facebook SDK's information but could not find a solution. If I must decode, which language/library would be the best performing at this type of operation?
PS. I plan on using cordova later to create a mobile app so I must use only Javascript on the front end and can't use a server language such as php to create html for the client.
Decoding the signed request will not kill your server. It's way fast than making an external request.
If you're using php you should look into the Facebook SDK for PHP and use this helper: https://developers.facebook.com/docs/php/FacebookJavaScriptLoginHelper/4.0.0
Normally Cookies are stored in the following location:
C:\Users\SomeUser\AppData\Roaming\Microsoft\Windows\Cookies
What i want to do is write cookie in a text file at this location using c# which is quite simple no problem at all, this is ok.
But i am not able to find a way to read cookie from that file using java-script in my web application.
Is it even possible?
JavaScript has no privileges reading files from the disc. You can't make a cross-domain request from a local file because it's not on a domain. You need to host C:\index.html on a local webserver instance in order for it to work. Or start Chrome with the following parameters.
--disable-web-security -–allow-file-access-from-files
You should also add the following to your service response:
response.setHeader("Access-Control-Allow-Origin", "*");
I believe it is possible, but due to the security issues it's won't be straight forward.
Check this jQuery lib: https://github.com/carhartl/jquery-cookie
Note: Some browsers for eg. Chrome, restrict from using coockies from file : Why does Chrome ignore local jQuery cookies?
I think u looking for this answer that u mention on comment..
i want the user to be automatically logged in if user is already logged in my desktop application, using cookies i want to pass some information of logged in user to the browser
. For that you need to generate a token that can be used for a one-time login that is stored in the database and Make sure tokens expire if they haven't been used in e.g. 8 hours. When you start the website, pass the token on the query string to the website. Then the website uses the token to connect the user's session to their account, and the token gets deleted.
Also you can use Single sign on WIKI
After struggling alot and searching, i found a way to do it. We can use InternetSetCookie method which is in wininet.dll to set cookie for a specific url or web application.
Add this code in your class:
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool InternetSetCookie(string url, string name, string data);
public static bool SetWinINETCookieString(string url, string name, string data)
{
return Form1.InternetSetCookie(url, name, data);
}
Usage:
var cookieOutput = SetWinINETCookieString("http://localhost:49549/Home/Index", "dataToTest", "thisIsTheData;Expires = " + DateTime.Now.AddDays(10).ToString("R"));
For testing purpose i hardcoded my application specific url.
and then in web application i wrote this javascript to get the cookie value:
$(document).ready(function () {
alert(getCookie("dataToTest"));
});
and here is getCookie function:
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
This SO post really helped me out.
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;
}
//...