Skip to content

Commit

Permalink
Merge branch 'ignore-account-hints' of https://github.com/AzureAD/mic…
Browse files Browse the repository at this point in the history
…rosoft-authentication-library-for-js into ignore-account-hints
  • Loading branch information
tnorling committed Mar 31, 2021
2 parents 6ae949c + be90e3d commit 56badd2
Show file tree
Hide file tree
Showing 47 changed files with 604 additions and 223 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Update samples and docs with event payload typecasting #3360",
"packageName": "@azure/msal-angular",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Update MsalInterceptor types and getScopesForEndpoint with query and relative paths #3307",
"packageName": "@azure/msal-angular",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Export PopupEvent #3360",
"packageName": "@azure/msal-browser",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Add AT PoP documentation (#3071)",
"packageName": "@azure/msal-browser",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Update StringUtils.matchPattern to account for queries in string #3307",
"packageName": "@azure/msal-common",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Update AccountInfo to refer to typedocs (#3266)",
"packageName": "@azure/msal-common",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Fix syntax in docs #3326",
"packageName": "@azure/msal-react",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Update Readme",
"packageName": "@azure/msal-react",
"email": "[email protected]",
"dependentChangeType": "none"
}
7 changes: 7 additions & 0 deletions change/msal-12d2764f-51e6-49b0-a48b-39ded19ba8a7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Fix token cache for /consumers authority #3327",
"packageName": "msal",
"email": "[email protected]",
"dependentChangeType": "patch"
}
6 changes: 3 additions & 3 deletions experimental/msal-react-native-android-poc/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions lib/msal-angular/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Microsoft Authentication Library for Angular


Note: MSAL Angular v2 is under development.

![npm (scoped)](https://img.shields.io/npm/v/@azure/msal-angular)![npm](https://img.shields.io/npm/dw/@azure/msal-angular)

| <a href="https://docs.microsoft.com/azure/active-directory/develop/tutorial-v2-angular" target="blank">Getting Started</a>| <a href="https://aka.ms/aaddevv2" target="_blank">AAD Docs</a> | <a href="https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_angular.html" target="_blank">Library Reference</a> | [Support](README.md#community-help-and-support) | <a href="https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/msal-angular-v2-samples" target="blank">Samples</a>
Expand Down
21 changes: 19 additions & 2 deletions lib/msal-angular/docs/v2-docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class AppComponent implements OnInit, OnDestroy {
filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
takeUntil(this._destroying$)
)
.subscribe((result) => {
.subscribe((result: EventMessage) => {
// Do something with the result
});
}
Expand All @@ -40,8 +40,25 @@ export class AppComponent implements OnInit, OnDestroy {
}
```

Note that you may need to cast the `result.payload` as a specific type to prevent compilation errors. The payload type will depend on the event, and can be found in our documentation [here](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/events.md).

```javascript
ngOnInit(): void {
this.msalBroadcastService.msalSubject$
.pipe(
filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
)
.subscribe((result: EventMessage) => {
// Casting payload as AuthenticationResult to access account
const payload = result.payload as AuthenticationResult;
this.authService.instance.setActiveAccount(payload.account);
});
}
```



For the full example of using events, please see our sample [here](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/samples/msal-angular-v2-samples/angular10-sample-app/src/app/app.component.ts#L29).
For the full example of using events, please see our sample [here](https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/d46c4455243bd51767f669a13fbb717d786c6716/samples/msal-angular-v2-samples/angular11-sample-app/src/app/home/home.component.ts#L17).

## Table of events

Expand Down
22 changes: 11 additions & 11 deletions lib/msal-angular/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/msal-angular/src/msal.interceptor.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import { PopupRequest, RedirectRequest, InteractionType, SilentRequest } from "@

export type MsalInterceptorConfiguration = {
interactionType: InteractionType.Popup | InteractionType.Redirect;
protectedResourceMap: Map<string, Array<string>>;
protectedResourceMap: Map<string, Array<string> | null>;
authRequest?: Omit<PopupRequest, "scopes"> | Omit<RedirectRequest, "scopes"> | Omit<SilentRequest, "scopes">;
};
130 changes: 124 additions & 6 deletions lib/msal-angular/src/msal.interceptor.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TestBed } from '@angular/core/testing';
import { HTTP_INTERCEPTORS, HttpClient } from "@angular/common/http";
import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
import { Location } from "@angular/common";
import { RouterTestingModule } from "@angular/router/testing";
import { AccountInfo, AuthError, InteractionType, IPublicClientApplication, PublicClientApplication } from '@azure/msal-browser';
import { MsalModule, MsalService, MsalInterceptor, MsalBroadcastService } from './public-api';
Expand Down Expand Up @@ -40,7 +41,10 @@ function MSALInterceptorFactory(): MsalInterceptorConfiguration {
["https://api.test.com", ["default.scope1"]],
["https://*.test.com", ["default.scope2"]],
["http://localhost:3000/unprotect", null],
["http://localhost:3000/", ["base.scope"]]
["http://localhost:3000/", ["base.scope"]],
["http://apps.com/tenant?abc", ["query.scope"]],
["http://applicationA/slash/", ["custom.scope"]],
["http://applicationB/noSlash", ["custom.scope"]]
])
}
}
Expand All @@ -62,7 +66,8 @@ function initializeMsal() {
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true,
}
},
Location
],
});

Expand Down Expand Up @@ -91,22 +96,24 @@ describe('MsalInterceptor', () => {
});
});

it("does not attach authorization header for unprotected resource", () => {
it("does not attach authorization header for unprotected resource", (done) => {
httpClient.get("http://localhost/api").subscribe(response => expect(response).toBeTruthy());

const request = httpMock.expectOne("http://localhost/api");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toBeUndefined;
httpMock.verify();
done();
});

it("does not attach authorization header for own domain", () => {
it("does not attach authorization header for own domain", (done) => {
httpClient.get("http://localhost:4200").subscribe(response => expect(response).toBeTruthy());

const request = httpMock.expectOne("http://localhost:4200");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toBeUndefined;
httpMock.verify();
done();
});

it("attaches authorization header with access token for protected resource with exact match", done => {
Expand Down Expand Up @@ -184,7 +191,7 @@ describe('MsalInterceptor', () => {
}, 200);
});

it("attaches authorization header with access token to urlfor protected resource with wildcard, url has multiple slashes", done => {
it("attaches authorization header with access token to url for protected resource with wildcard, url has multiple slashes", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
Expand Down Expand Up @@ -272,13 +279,14 @@ describe('MsalInterceptor', () => {
}, 200);
});

it("does not attach authorization header when scopes set to null, and resource is before any base url or wildcards", () => {
it("does not attach authorization header when scopes set to null, and resource is before any base url or wildcards", done => {
httpClient.get("http://localhost:3000/unprotect").subscribe(response => expect(response).toBeTruthy());

const request = httpMock.expectOne("http://localhost:3000/unprotect");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toBeUndefined;
httpMock.verify();
done();
});

it("attaches authorization header with access token from acquireTokenPopup if acquireTokenSilent fails in interceptor and interaction type is Popup", done => {
Expand Down Expand Up @@ -341,4 +349,114 @@ describe('MsalInterceptor', () => {
}, 200);
});

it("attaches authorization header with access token for protected resource with queries", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
resolve({
accessToken: "access-token"
});
})
));

spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([sampleAccountInfo]);

httpClient.get("http://apps.com/tenant?abc").subscribe();
setTimeout(() => {
const request = httpMock.expectOne("http://apps.com/tenant?abc");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toEqual("Bearer access-token");
httpMock.verify();
done();
}, 200);
});

it("attaches authorization header with access token for protected resource with trailing slash", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
resolve({
accessToken: "access-token"
});
})
));

spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([sampleAccountInfo]);

httpClient.get("http://applicationA/slash").subscribe();
setTimeout(() => {
const request = httpMock.expectOne("http://applicationA/slash");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toEqual("Bearer access-token");
httpMock.verify();
done();
}, 200);
});

it("attaches authorization header with access token for endpoint with trailing slash", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
resolve({
accessToken: "access-token"
});
})
));

spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([sampleAccountInfo]);

httpClient.get("http://applicationB/noSlash/").subscribe();
setTimeout(() => {
const request = httpMock.expectOne("http://applicationB/noSlash/");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toEqual("Bearer access-token");
httpMock.verify();
done();
}, 200);
});

it("attaches authorization header with access token for relative endpoint", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
resolve({
accessToken: "access-token"
});
})
));

spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([sampleAccountInfo]);

httpClient.get("/v1.0/me").subscribe();
setTimeout(() => {
const request = httpMock.expectOne("/v1.0/me");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toEqual("Bearer access-token");
httpMock.verify();
done();
}, 200);
});

it("attaches authorization header with access token for relative endpoint which includes query", done => {
spyOn(PublicClientApplication.prototype, "acquireTokenSilent").and.returnValue((
new Promise((resolve) => {
//@ts-ignore
resolve({
accessToken: "access-token"
});
})
));

spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([sampleAccountInfo]);

httpClient.get("/tenant?abc").subscribe();
setTimeout(() => {
const request = httpMock.expectOne("/tenant?abc");
request.flush({ data: "test" });
expect(request.request.headers.get("Authorization")).toEqual("Bearer access-token");
httpMock.verify();
done();
}, 200);
});

});
Loading

0 comments on commit 56badd2

Please sign in to comment.