Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose idTokenClaims on AccountInfo #2554

Merged
merged 14 commits into from
Dec 2, 2020
6 changes: 1 addition & 5 deletions lib/msal-browser/src/cache/BrowserCacheManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,15 @@ export class BrowserCacheManager extends CacheManager {
// Window storage object (either local or sessionStorage)
private browserStorage: IWindowStorage;
// Client id of application. Used in cache keys to partition cache correctly in the case of multiple instances of MSAL.
private clientId: string;
private cryptoImpl: CryptoOps;
private logger: Logger;

// Cookie life calculation (hours * minutes * seconds * ms)
private readonly COOKIE_LIFE_MULTIPLIER = 24 * 60 * 60 * 1000;

constructor(clientId: string, cacheConfig: CacheOptions, cryptoImpl: CryptoOps, logger: Logger) {
super();
super(clientId, cryptoImpl);

this.cacheConfig = cacheConfig;
this.clientId = clientId;
this.cryptoImpl = cryptoImpl;
this.logger = logger;

this.browserStorage = this.setupBrowserStorage(cacheConfig.cacheLocation);
Expand Down
3 changes: 3 additions & 0 deletions lib/msal-common/src/account/AccountInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
* - tenantId - Full tenant or organizational id that this account belongs to
* - username - preferred_username claim of the id_token that represents this account
* - name - Full name for the account, including given name and family name
* - idTokenClaims - Object contains claims from ID token
* - localAccountId - The user's account ID
*/
export type AccountInfo = {
homeAccountId: string;
environment: string;
tenantId: string;
username: string;
name?: string;
idTokenClaims?: object;
sameerag marked this conversation as resolved.
Show resolved Hide resolved
localAccountId?: string;
};
21 changes: 18 additions & 3 deletions lib/msal-common/src/cache/CacheManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ import { TrustedAuthority } from "../authority/TrustedAuthority";
import { AppMetadataEntity } from "./entities/AppMetadataEntity";
import { ServerTelemetryEntity } from "./entities/ServerTelemetryEntity";
import { ThrottlingEntity } from "./entities/ThrottlingEntity";
import { AuthToken } from "../account/AuthToken";
import { ICrypto } from "../crypto/ICrypto";

/**
* Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
*/
export abstract class CacheManager implements ICacheManager {
protected clientId: string;
protected cryptoImpl: ICrypto;

constructor(clientId: string, cryptoImpl: ICrypto) {
jasonnutter marked this conversation as resolved.
Show resolved Hide resolved
this.clientId = clientId;
this.cryptoImpl = cryptoImpl;
}

/**
* fetch the account entity from the platform cache
Expand Down Expand Up @@ -146,9 +155,15 @@ export abstract class CacheManager implements ICacheManager {
return [];
} else {
const allAccounts = accountValues.map<AccountInfo>((value) => {
let accountObj: AccountEntity = new AccountEntity();
accountObj = CacheManager.toObject(accountObj, value) as AccountEntity;
return accountObj.getAccountInfo();
const accountEntity = CacheManager.toObject<AccountEntity>(new AccountEntity(), value);
const accountInfo = accountEntity.getAccountInfo();
const idToken = this.readIdTokenFromCache(this.clientId, accountInfo);
if (idToken && !accountInfo.idTokenClaims) {
accountInfo.idTokenClaims = new AuthToken(idToken.secret, this.cryptoImpl).claims;
jasonnutter marked this conversation as resolved.
Show resolved Hide resolved
}

return accountInfo;

});
return allAccounts;
}
Expand Down
9 changes: 8 additions & 1 deletion lib/msal-common/src/cache/entities/AccountEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { AccountInfo } from "../../account/AccountInfo";
import { ClientAuthError } from "../../error/ClientAuthError";
import { AuthorityType } from "../../authority/AuthorityType";
import { Logger } from "../../logger/Logger";
import { TokenClaims } from "../../account/TokenClaims";

/**
* Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).
Expand All @@ -38,6 +39,7 @@ import { Logger } from "../../logger/Logger";
* lastModificationTime: last time this entity was modified in the cache
* lastModificationApp:
* oboAssertion: access token passed in as part of OBO request
* idTokenClaims: Object containing claims parsed from ID token
* }
*/
export class AccountEntity {
Expand All @@ -52,6 +54,7 @@ export class AccountEntity {
lastModificationTime?: string;
lastModificationApp?: string;
oboAssertion?: string;
idTokenClaims?: TokenClaims;

/**
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
Expand Down Expand Up @@ -102,6 +105,7 @@ export class AccountEntity {
tenantId: this.realm,
username: this.username,
name: this.name,
idTokenClaims: this.idTokenClaims,
localAccountId: this.localAccountId
};
}
Expand Down Expand Up @@ -149,8 +153,10 @@ export class AccountEntity {
// non AAD scenarios can have empty realm
account.realm = idToken.claims.tid || "";
account.oboAssertion = oboAssertion;

if (idToken) {
account.idTokenClaims = idToken.claims;

// How do you account for MSA CID here?
const localAccountId = !StringUtils.isEmpty(idToken.claims.oid)
? idToken.claims.oid
Expand Down Expand Up @@ -195,6 +201,7 @@ export class AccountEntity {

account.environment = env;
account.username = idToken.claims.upn;
account.idTokenClaims = idToken.claims;
/*
* add uniqueName to claims
* account.name = idToken.claims.uniqueName;
Expand Down
2 changes: 1 addition & 1 deletion lib/msal-common/src/config/ClientConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export function buildClientConfiguration(
authOptions: { ...DEFAULT_AUTH_OPTIONS, ...userAuthOptions },
systemOptions: { ...DEFAULT_SYSTEM_OPTIONS, ...userSystemOptions },
loggerOptions: { ...DEFAULT_LOGGER_IMPLEMENTATION, ...userLoggerOption },
storageInterface: storageImplementation || new DefaultStorageClass(),
storageInterface: storageImplementation || new DefaultStorageClass(userAuthOptions.clientId, cryptoImplementation),
networkInterface: networkImplementation || DEFAULT_NETWORK_IMPLEMENTATION,
cryptoInterface: cryptoImplementation || DEFAULT_CRYPTO_IMPLEMENTATION,
clientCredentials: clientCredentials || DEFAULT_CLIENT_CREDENTIALS,
Expand Down
7 changes: 4 additions & 3 deletions lib/msal-node/src/cache/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
Logger,
ValidCacheType,
CredentialEntity,
CredentialType
CredentialType,
ICrypto
} from "@azure/msal-common";
import { Deserializer } from "./serializer/Deserializer";
import { Serializer } from "./serializer/Serializer";
Expand All @@ -30,8 +31,8 @@ export class Storage extends CacheManager {
private cache: CacheKVStore = {};
private changeEmitters: Array<Function> = [];

constructor(logger: Logger) {
super();
constructor(logger: Logger, clientId: string, cryptoImpl: ICrypto) {
super(clientId, cryptoImpl);
this.logger = logger;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/msal-node/src/client/ClientApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ export abstract class ClientApplication {
protected constructor(configuration: Configuration) {
this.config = buildAppConfiguration(configuration);
this.logger = new Logger(this.config.system!.loggerOptions!);
this.storage = new Storage(this.logger);
this.cryptoProvider = new CryptoProvider();
this.storage = new Storage(this.logger, this.config.auth.clientId, this.cryptoProvider);
this.tokenCache = new TokenCache(
this.storage,
this.logger,
this.config.cache!.cachePlugin
);
this.cryptoProvider = new CryptoProvider();
TrustedAuthority.setTrustedAuthoritiesFromConfig(this.config.auth.knownAuthorities!, this.config.auth.cloudDiscoveryMetadata!);
}

Expand Down