{"version":3,"sources":["../../../packages/core/security/sign-on-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,KAAK,EAAE,sBAAsB,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,aAAa;IACtB;;OAEG;IACH,OAAO,CAAC,oBAAoB,CAAa;IAEzC;;OAEG;IACI,sBAAsB,EAAE,sBAAsB,CAAC;IAEtD;;OAEG;IACI,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAExD;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAA8B;IAExD;;OAEG;IACH,OAAO,CAAC,WAAW,CAAwC;IAE3D;;OAEG;gBACS,WAAW,EAAE,MAAM,UAAU,CAAC,mBAAmB,CAAC;IAQ9D;;OAEG;IACH,IAAW,oBAAoB,IAAI,OAAO,CAEzC;IAED;;OAEG;IACH,IAAW,wBAAwB,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAMpE;IAED;;OAEG;IACI,2BAA2B,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI;IAQvE;;;OAGG;IACI,oBAAoB,IAAI,UAAU,CAAC,mBAAmB,CAAC;IAW9D;;;;;OAKG;IACI,0BAA0B,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO;IAKlF;;;;;;OAMG;IAEI,uBAAuB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC;IAUrH;;;OAGG;IACI,gCAAgC,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAU7E;;OAEG;IACI,6BAA6B,CAChC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,UAAU,CAAC,gBAAgB,CAAC;IAYpH;;;OAGG;IACI,yBAAyB,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,IAAI;CAGxD","file":"sign-on-manager.d.ts","sourcesContent":["/* eslint-disable unused-imports/no-unused-vars */\r\nimport { Observable, Subject } from 'rxjs';\r\nimport { AjaxError, AjaxRequest } from 'rxjs/ajax';\r\nimport { filter, map, timeout } from 'rxjs/operators';\r\nimport { CimStreamOptions, CimStreamResponse } from '../data/cim-stream';\r\nimport { headerConstants, HttpStatusCode } from '../data/http-constants';\r\nimport { Net } from '../data/net';\r\nimport { PowerShellStreamResponse } from '../data/powershell-stream';\r\n\r\n/**\r\n * Defines an signed http request token\r\n */\r\nexport interface SignedHttpRequestToken {\r\n    /**\r\n     * JSON Web Token (string).\r\n     */\r\n    jwt: string;\r\n\r\n    /**\r\n     * User name.\r\n     */\r\n    username: string;\r\n}\r\n\r\nexport interface SignOnTokenResponse {\r\n    /**\r\n     * The time aquired.\r\n     */\r\n    time: number;\r\n\r\n    /**\r\n     * The signed http request token.\r\n     */\r\n    token: SignedHttpRequestToken;\r\n}\r\n\r\nexport interface SignOnTokenRefresh {\r\n    /**\r\n     * The time aquired.\r\n     */\r\n    time: number;\r\n}\r\n\r\n/**\r\n * Manage Signed HTTP Request token (Proof of possession token) handling.\r\n */\r\nexport class SignOnManager {\r\n    /**\r\n     * Wait for one minute to respond by the portal.\r\n     */\r\n    private portalMaxWaitTimeout = 60 * 1000;\r\n\r\n    /**\r\n     * The PoP Authorization Token.\r\n     */\r\n    public signedHttpRequestToken: SignedHttpRequestToken;\r\n\r\n    /**\r\n     * The sign on token awaiter subject.\r\n     */\r\n    public signOnTokenAwaiter: Subject<SignOnTokenResponse>;\r\n\r\n    /**\r\n     * The sign on token requester subject.\r\n     */\r\n    private signOnTokenRefresh: Subject<SignOnTokenRefresh>;\r\n\r\n    /**\r\n     * The refresh request to the authorization manager.\r\n     */\r\n    private refreshCall: () => Observable<SignOnTokenResponse>;\r\n\r\n    /**\r\n     * Initializes a new instance of the SignOnManager class.\r\n     */\r\n    constructor(refreshCall: () => Observable<SignOnTokenResponse>) {\r\n        this.refreshCall = refreshCall;\r\n        if (MsftSme.isShell()) {\r\n            this.signOnTokenAwaiter = new Subject<SignOnTokenResponse>();\r\n            this.signOnTokenRefresh = new Subject<SignOnTokenRefresh>();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets a valude indicating whethere sign on token is active and configured.\r\n     */\r\n    public get isSignOnTokenEnabled(): boolean {\r\n        return !!this.signedHttpRequestToken;\r\n    }\r\n\r\n    /**\r\n     * Gets the sign on token request observable by Shell.\r\n     */\r\n    public get signOnTokenRefreshTarget(): Observable<SignOnTokenRefresh> {\r\n        if (this.signOnTokenRefresh == null) {\r\n            throw new Error('Request object is only for Shell.');\r\n        }\r\n\r\n        return this.signOnTokenRefresh.asObservable();\r\n    }\r\n\r\n    /**\r\n     * Apply signed http request token.\r\n     */\r\n    public applySignedHttpRequestToken(token: SignedHttpRequestToken): void {\r\n        if (token) {\r\n            const time = Date.now();\r\n            this.signedHttpRequestToken = token;\r\n            this.signOnTokenAwaiter.next({ time, token });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Request sign on token to refresh.\r\n     * @returns success void.\r\n     */\r\n    public requestSignOnRefresh(): Observable<SignOnTokenResponse> {\r\n        const now = Date.now();\r\n        const awaiter = this.signOnTokenAwaiter\r\n            .pipe(\r\n                filter(token => token.time > now),\r\n                timeout(this.portalMaxWaitTimeout)\r\n            );\r\n        this.signOnTokenRefresh.next({ time: now });\r\n        return awaiter;\r\n    }\r\n\r\n    /**\r\n     * Check if it can handle unauthorized login case.\r\n     * @param code the error code.\r\n     * @param error the ajax error response.\r\n     * @returns true if it can handle.\r\n     */\r\n    public canHandleUnauthorizedLogin(code: HttpStatusCode, error: AjaxError): boolean {\r\n        // unauthorized login was observed.\r\n        return Net.isUnauthorizedLogin(error);\r\n    }\r\n\r\n    /**\r\n     * Handles the unauthorized login case.\r\n     * @param code the error code.\r\n     * @param request the ajax request.\r\n     * @param error the ajex error reponse.\r\n     * @returns success if it could handled.\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n    public handleUnauthorizedLogin(code: HttpStatusCode, request: AjaxRequest, error: AjaxError): Observable<AjaxRequest> {\r\n        // request new Sign On token to the parent frame which is Azure Compute VM UI.\r\n        return this.refreshCall()\r\n            .pipe(map(() => {\r\n                // update with newly aquired PoP jwt token.\r\n                this.SetAadAuthorizationHeader(request.headers);\r\n                return request;\r\n            }));\r\n    }\r\n\r\n    /**\r\n     * Check if it can handle unauthorized login case.\r\n     * @param response the response of CIM stream query.\r\n     */\r\n    public canHandleStreamUnauthorizedLogin(response: CimStreamResponse): boolean {\r\n        // access denied case.\r\n        const responseObject = response && response.response;\r\n        if (!responseObject) {\r\n            return false;\r\n        }\r\n\r\n        return responseObject.statusCode === HttpStatusCode.Unauthorized && responseObject.forbidden && responseObject.forbidden === 'UnauthorizedLogin';\r\n    }\r\n\r\n    /**\r\n     * Handle returns true for an ajax error, this method can be called to handle that error.\r\n     */\r\n    public handleStreamUnauthorizedLogin(\r\n        options: CimStreamOptions, response: CimStreamResponse | PowerShellStreamResponse): Observable<CimStreamOptions> {\r\n        let message = response.response.error && response.response.error.message;\r\n        if (!message) {\r\n            const errors = response.response.errors;\r\n            if (errors && errors.length > 0) {\r\n                message = errors[0].message;\r\n            }\r\n        }\r\n\r\n        return this.refreshCall().pipe(map(() => options));\r\n    }\r\n\r\n    /**\r\n     * Set AAD authorization header.\r\n     * @param headers the headers.\r\n     */\r\n    public SetAadAuthorizationHeader(headers?: any): void {\r\n        headers[headerConstants.SME_AAD_AUTHORIZATION] = `WAC;PAS ${this.signedHttpRequestToken.jwt}`;\r\n    }\r\n}\r\n"]}