SharePoint Gantt Chart Hidden with Bootstrap Master Page

SharePoint provides a Gantt chart web part that allows small teams to manage their projects. When using the default master pages, the web part renders with no problem.  In the cases when a custom Bootstrap master page is used, the right side panel of the Gantt grid does not display properly as shown on the image below:

By taking a look at the problem, we notice that Bootstrap uses the following CSS rule:

* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;

This causes the chart to not display properly because there is a CSS rule on the Gantt chart that sets a border on the date header. We can key on that element rule to override the Bootstrap style by adding the following to our custom CSS file that is loaded from the master page.

/*find inline style with the border rule at the end. */
div[style$="border: 1px solid rgb(171, 171, 171);"]
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;
    box-sizing: content-box;

We want to override the rule just for that specific element and not affect other layout elements.  We have to use this selector because the server side controllers create dynamic ids on the elements, and we want to prevent this problem in any page where this web part is used.

The solution was to find inline styles set with a border to use a box-sizing content-box instead of border-box. This prevents the hidden behavior on the Gantt chart. After the change, our page should look like this:

Hope you can now see the chart.

Originally published by ozkary.com


Presentation Securing Web Apps with Azure AD

This is the presentation for the Securing Web Apps with Azure AD.  In this presentation, we talked about the following areas:

  • We take a Web application with an AngularJS SPA as client and NodeJS server with no security context, and we deploy it to Azure using a local GIT repository.
  • We configure the Azure Application with Azure AD and show the different behaviors with forcing the users to Login or allowing anonymous access.
  • We also discuss how to change a NodeJS server application and handle the security implementation in the server code.
  • We finally show how to make the implementation changes on the AngularJS SPA to allow the application to directly integrate with Azure AD.
Related Blog Entries:

For the code, visit:


Originally published by ozkary.com


SQL Server BCP Import Skip and Map Columns Using Views

The BCP (bulk copy program) command line utility enables us to quickly import CSV files into a SQL Server database. The utility works very well when the import file matches the structure of the table, and the table does not have an identity column.

The moment the import file does not match the structure of the table with can run into different possible errors during the import.  This is mostly due to the fact that the fields may not mapped correctly to the columns on the table.

To facilitate the control of how the CSV fields should be mapped to the fields on the table, we can create a view that matches the CSV field order.  Let’s take a look at an example to illustrate the problem and a solution using SQL views.

The Table

This is a simple table that allows us to store blog entries.  We should note the identity and default datetime columns which would not exist in a CSV file as these are system generated values.

CREATE TABLE dbo.ozkary_blog
       id       int identity,
       title    nvarchar(200) null,
       url      nvarchar(100) null,
       tags     nvarchar(100) null,
       created  datetime null,
       imported datetime default(getdate()) not null

The CSV File

Our CSV file contains four fields which are fewer fields than columns on the table.


We should note the following possible issues when trying to import this CSV file with our previously define table.

  • The order of the columns on the table does not match the fields of the CSV file. The create date field is first on the file, but it is on position five on our table.

  • Our table has an identity field which sure will not match the date field on position one of our CSV file.

  • Our table also has an import date time field with a default date value.

Data Import Process

Let’s attempt to import the data directly into our table without any modifications. To import the file, we execute the following command:

bcp dataimport.dbo.ozkary_blog IN ".\\ozkary_blog.csv" -t, -c -F1 -S .\sqlexpress -T

When calling the BCP utility we use the following parameters:

Parameter  Option
Database and table name
This is the database and table name
CSV file name and location
This is the file location and name
Comma is the field delimiter
Use char as the storage type for all the fields
Start at row 2 column - skip field headers
Server name
Use a trusted connection with the current session

In our first attempt to import the data, we are using the table name. This does not work because of fields mapping to the wrong columns, and ,as expected, we get some data type errors (add –e bcp.log parameter to create a log file and see more detail on the errors)

Solution – Using a View to Map the Fields

To address this problem, we can create a view that only uses the fields that are available on the import file and match their corresponding order.

CREATE VIEW dbo.vw_import_ozkary_blog
   SELECT created,title,url,tags
   FROM dbo.ozkary_blog

We should now modify the command and use the view name instead of the table name. This should provide better results.

bcp dataimport.dbo.vw_import_ozkary_blog IN ".\\ozkary_blog.csv" -t, -c -F2 -S .\sqlexpress -T

By looking at the output on the image above, 3 rows got imported. If we query our table we should see the records with our identity and imported date values.

As shown, the approach of importing a CSV file using a database view provides a consistent and simple way to map and skip table columns during a BCP import.

Hope it helps.

Originally published by ozkary.com


Nodejs Passport Azure AD Authentication

In a previous article, we discussed how to enable an application with Azure AD without making any implementation changes that integrate directly with Azure AD API. With that type of integration, we saw how all of our content is protected under the Azure security platform. We also noticed that there is a limitation when we need to provide anonymous access to some of the resources. In this article, we take a look at how to address this limitation by taking a direct control of the security in our application.

To download the code, clone the repo from Github with the following command:

git clone https://github.com/ozkary/nodejs-azure-ad.git

This creates a new folder (nodejs-azure-ad) and downloads the code. The code for this article is in the master branch. The simple-auth branch has the code for the first article in which we are only enabling the authentication for the entire app.

Nodejs Passport Azure AD Authentication

We now need to enable the security to allow anonymous requests. We start by looking at the options that are available on Azure. Let’s get back to Azure and select our web app. Click on Select Settings -> Authentication / Authorization  and click on On for the App Service Authentication option. This enables additional options for the actions to take when a request is not authenticated. We can select either of the following options:

  1. Log in with Azure Active Directory
  2. Allow Anonymous requests (no action)
The first option forces a redirect and does not allow the option to provide anonymous access to any of the app content. When we need to provide anonymous access to some of our application resources, we need to select the second option which allows anonymous requests to pass through. This passes the authorization concerns to our application logic.

Handling Authorization

After we enable the option to Allow Anonymous requests, the application is enabled to receive all the requests. It is the responsibility of the application to determine what should be protected using authorization filters which in turn can redirect the traffic to an identity provider like Azure AD. The identity provider is the system that presents the login view to the users.

Install the supporting libraries

In order to implement our authorization logic, we need to integrate directly with Azure AD. Lucky for us, there are plenty libraries that can help enable our integration. Let’s start by installing a few of those libraries in our application. Run the following command from the command line in the working directory where the code has been cloned.

Note: These libraries have already been configured on the package.json file, but these steps are shown to clearly show what libraries are required for this integration.

npm install –save passport –save

The passport library helps us authenticate the requests by leveraging several strategy plugins to delegate the authentication of users over different protocols. For more information on this library visit: https://www.npmjs.com/package/passport

npm install passport-azure-ad-oauth2 --save

We also install the passport azure ad oath library which is the strategy that password uses to provide the authentication over the OAuth 2.0 protocol which is supported by Azure AD. For more information visit: https://www.npmjs.com/package/passport-azure-ad-oauth2

npm install express-session --save

The last library to install is needed for session management. This is what passport uses to manage the persisted user information.

Authorization Module

Now that we have the libraries installed, we can move forward with the implementation of our custom authorization module.  The approach is to initialize the OAuth strategy plugin with our Azure AD application settings which can be obtained from Azure. We need the following information:

This is our application id

Client Secret
This is an app key that can be generated from azure and that can be set to expire. See next section for more information
Callback Url
This the url that the identity provider service can use to send back the response after the user authenticates.

Generate App key/secret

To generate the app key, we need to go back to azure and visit the AD app settings: Azure Active Directory->Application Registration -> APP Name->Settings->Keys.

We can now type the key description and set the duration. The key value is generated automatically after we save the settings. We need to copy the key information before moving away from this blade as described in this next image: (The key displayed on the image is no longer valid)

App Secret Key

From the settings blade, we click on the Properties option. This is where we can find the application id and return Url.  After we collect our app information, we can now initialize our passport strategy with the following code in our modules/auth.js file: (replace #s with your app information)

var passport = require('passport');
var oauthStrategy = require('passport-azure-ad-oauth2').Strategy;

module.exports.init = function(app, $users)

    var strategy = new oauthStrategy({
                        clientID: '####',      //app id
                        clientSecret: '####',   //your app key                    
                        callbackURL: 'https://####.azurewebsites.net/onauth',                                        
                    },function(accessToken, refresh_token, params, profile, done){
                        //decodes the token and sends the information to the user profile handler
                        var context = profile;
                        done(null, context);

The code above sets the app information, so the strategy plugin can provide the app registration to the Azure identity provider.  In the callback url parameter, we need to add a route, so we are able to write a handler for the callback. In this case, we add the onauth route for which a handler is implemented by our modules/route.js module which is cover in a coming section.

The anonymous method on the oauth strategy is called when the authentication is successful. It receives the profile information which is a Jason Web Token (JWT). By calling the done callback with the user context/profile, we are passing the execution to the strategy userProfile handler which takes care of parsing the token and reading the claims from the token. This is the area of the code where we need to transform JWT format into our custom user context JSON format.

Note: The authentication process is started by calling password authenticate in our authorization filter code. We can see this implementation in the Authorization Filter section.

        //user profile handler to parse the data and create the user profile
        strategy.userProfile = function (accessToken, done) {
            var profile = {};
            try {
                var tokenBase64 = accessToken.split('.')[1];
                var tokenBinary = new Buffer(tokenBase64, 'base64');
                var tokenAscii = tokenBinary.toString('ascii');
                var tokenObj = JSON.parse(tokenAscii);             
                profile.id = tokenObj.upn;
                profile.email = tokenObj.upn; //upn is the email on AD
                profile.displayname = tokenObj.given_name + ' ' + tokenObj.family_name;
                done(null, profile);
                console.log('user profile', profile);
            } catch (ex) {
                console.log("Unable to parse oauth2 token from WAAD.");
                done(ex, null);

Once our user context is created, we call the done callback with the custom model. This passes execution to the passport serialize user function which is the area where we should add the user information to a session storage. In our example, we are using in-memory hash table to illustrate the process.

        //writes to local session
        passport.serializeUser(function (user, done) {
            $users[user.id] = user;
            done(null, user.id);

        //gets from local session
        passport.deserializeUser(function (id, done) {
            var user = $users[id];
            done(null, user);

App Permissions

We also need to set the app permissions to access the Microsoft Graph and be able to read the directory data. If this permission is not set, the app would not be able to have access to the Microsoft Resource identifier.  To enable the app permissions, we need to go back to azure and visit the AD app settings: Azure Active Directory->Application Registration ->APP Name->Settings->Required Permissions. From there we need to click on Add and select Microsoft Graph.  This enables other settings for which we need to check Read directory data as show below:

On our server code (modules/auth.js), we need to add the handler for the passport strategy token params. This sets passport with the resource Url which is used to get the authentication token.

    //Azure resource you're requesting access
    //prevents the Resource identifier is not provided error
    strategy.tokenParams = function(options) {
        return { resource: 'https://graph.windows.net' };

Authorization Filter

The deserialize user function is used by the passport session management process. The main purpose is to fetch the user context from a local cache to set the request as an authenticated request. This is what enables our authorization filter with the session/user context to allow access to the authorized areas of our application.

    //passport authorization filter
    passport.authorize = function authorize(req, res, next) {
        var auth = req.isAuthenticated();

        if (req.isAuthenticated() || req.user) {
            return next();

        //authenticate the user
        passport.login()(req, res, next);

    //login extension method to validate the login state
    passport.login = function () {
        return passport.authenticate(azureOAuth,
                      { failureRedirect: '/',    failureFlash: true });

When the request is authenticated, we just return next which allows the request to continue. If no user context was found on the current request, we force the user to login by calling passport authenticate. This is the entry point for the passport authentication management process which consists of a series of redirects to the Single Sign On page presented by the identity provider system.

Application Routes

Now that we have the authorization filter ready, we need to secure our application routes. This is done by setting the filter on any route that should be under authentication. (modules\route.js)

    //secured api routes with no redirect
    function authorizeApi(req, res, next) {
        var auth = req.isAuthenticated();

        if (req.isAuthenticated()) {
            return next();
        } else {
            res.send(401, 'Not authorized');

    //authorize the routes
    app.use('/api/user', authorizeApi);
    app.use('/login', passport.authorize);

    //add the route handlers
    app.get('/api/user', profile)
    app.get('/login', login)

    //validate that the user profile is set on the authSession cookie
    function profile(req, resp) {
        resp.json({ session: req.user });

    function login(req, res) {
        res.sendFile(__dirname + "/app/index.html");

    //route handler for the post authentication from identity provider
    app.get('/onauth', passport.login(),
        function (req, res) {
            login(req, res);


We have two protected routes login and api/user.

Login Route

The login route starts the login process for the user. If the user is not logged on, the application uses the passports authorize filter to start the login process via HTTP redirects. This route is called from the login button on the client application.

api/user Route

This API route fetches the user information only when the user is logged on. If there is no active session, a HTTP 401 (not authorized) is returned. This is call every time the application loads to hide the login button and display the user content as shown below:

We should also note the onauth route which is our handler for the response from the identity provider after a successful login. On the handler, we call the passport login function to process the information and transform the token into our user context via the serialize user passport function.


We are now able to compare two possible integrations with Azure AD. When we select Login with Azure AD, we discover that Azure protects our application entirely and does not allow for any type of anonymous access to our resources.

In some cases, we need to provide the anonymous access and only protect some of the resources like API and/or server side controllers. For that scenario, we show how to select the Allow Anonymous Requests configuration option, use the passport libraries and Azure OAuth integration to take more direct control of our security.

We should note that the integration approach to take should be based on our application requirements.

Originally published by ozkary.com