3

I have an HTML application written in Angular JS, and I would like to allow other trusted internal developers to extend the application by creating their own applications in Angular hosted on different endpoints. The extensions want to be embedded inside the main shell by the use of <iframe>

These applications all exist in the same AAD Tenant, as different application registrations.

We have tried to set the iframe src="http://localhost:4200", and inside the inner application have used adal.js to authenticate against the AD. This inner application works fine when hosted directly in the browser, but when embedded in the iframe causes:

Refused to display 'https://login.microsoftonline.com/tenantid/oauth2/authorize?response_type=id_token&client_id=applicationId&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fhome&state=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxab&client-request-id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx&x-client-SKU=Js&x-client-Ver=1.0.17&nonce=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx' in a frame because it set 'X-Frame-Options' to 'deny'

Is what we are attempting to do sensible, or is this approach considered a security risk?

I have seen others solve this by also navigating to the child page, but then you lose the shell.

Here is the code from the AngularJS side:

var iframe = document.querySelector("#myiframe");
iframe.src = ENV.iframeURL + "/?data=" + $routeParams.data;

And, the code at the Angular Side is more complex:

Readme.md

I have copied in the readme.md file from the Angular application, so you can to get an insight on what we have done Angular side. Angular App works fine when it is the root of the web page.

Application details

The Main application has the authService injected into it, and onInit calls the applicationInit()

export class AppComponent implements OnInit {

  constructor(private authService: AuthService) {
  }

  ngOnInit() {

    this.authService.applicationInit();
  }
}

```

The Auth Service is the main part which you will use within your own projects. Referring to How to load adal.js in webpack inside Angular 2 (Azure-AD) for details on this workflow

/// <reference path="../../../node_modules/@types/adal/index.d.ts" />

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import 'expose-loader?AuthenticationContext!../../../node_modules/adal-angular/lib/adal.js';


@Injectable()
export class AuthService {
  private context: adal.AuthenticationContext = null;

  constructor() {
    let adalSettings = environment.adalSettings;
    let createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;
    this.context = new createAuthContextFn(adalSettings);
  }

Environment file while is loaded - loads in the relevant tenant, and applicationId

export const environment = {
  production: false,
  adalSettings: {
    tenant: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    clientId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    redirectUri: 'http://localhost:4200/home',
    postLogoutRedirectUri:'http://localhost:4200',
    expireOffsetSeconds: 300
  }
};

The current User use the service's getUser method: this returns a promise to the user

getUser(): Promise<adal.User> {

    var result = new Promise<adal.User>(
      (resolve, reject) => {
        this.context.getUser((err, user) => {
          if (err)
            resolve(null);
          else
            resolve(user);
        });

      });
    return result;


  }

## Routes into the application

const routes: Routes = [

    {
        path: 'login',
        component: LoginRedirectComponent
    },

    {
        path: 'home',
        component: HomeComponent,
        canActivate: [AuthGuard]
    },
    {
        path: '',
        pathMatch: 'full',
        redirectTo: 'home'
    }

];

//TODO add other client routes - e.g. the data which is being posted in

What are your recommendations? Is there a best practice we should be following?

Thanks in Advance

ChrisI
  • 41
  • 5
  • According to this page, https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/79 it looks like it is by design that the Identity management Login CAN NOT run in an iframe which does make sense from a security perspective. I am going to pursue getting the parent and child windows to talk to each other via PostMessage https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage – ChrisI Mar 20 '18 at 08:08

0 Answers0