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