Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,15 @@ dependencies:
aad_oauth: "^1.0.1"
```

## Language support

You can change your default user flow page language by defining:

```dart
final AadOAuth oauth = new AadOAuth(config);
oauth.setLanguage('en')
```

## Contribution

Contributions can be submitted as pull requests and are highly welcomed. Changes will be bundled together into a release. You can find the next release date and past releases in the [CHANGELOG file](CHANGELOG.md).
109 changes: 69 additions & 40 deletions assets/msalv2.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,76 @@ var aadOauth = (function () {
loginHint: null
};

function deriveAuthorityFromAuthorizationUrl(authorizationUrl) {
const oauthSuffixes = ['/oauth2/v2.0/authorize', '/oauth2/authorize'];

for (const suffix of oauthSuffixes) {
if (authorizationUrl.endsWith(suffix)) {
let authority = authorizationUrl.substring(0, authorizationUrl.length - suffix.length);
if (!authority.endsWith('/')) {
authority += '/';
}
return authority;
}
}

return authorizationUrl.endsWith('/') ? authorizationUrl : authorizationUrl + '/';
}

// Initialise the myMSALObj for the given client, authority and scope
function init(config) {
// TODO: Add support for other MSAL configuration
var authData = {
clientId: config.clientId,
authority: config.isB2C ? "https://" + config.tenant + ".b2clogin.com/tfp/" + config.tenant + ".onmicrosoft.com/" + config.policy + "/" : "https://login.microsoftonline.com/" + config.tenant,
knownAuthorities: [ config.tenant + ".b2clogin.com", "login.microsoftonline.com"],
redirectUri: config.redirectUri,
};
var postLogoutRedirectUri = {
postLogoutRedirectUri: config.postLogoutRedirectUri,
};
var msalConfig = {
auth: config?.postLogoutRedirectUri == null ? {
...authData,
} : {
...authData,
...postLogoutRedirectUri,
},
cache: {
cacheLocation: config.cacheLocation,
storeAuthStateInCookie: false,
},
};

if (typeof config.scope === "string") {
tokenRequest.scopes = config.scope.split(" ");
} else {
tokenRequest.scopes = config.scope;
}

tokenRequest.extraQueryParameters = JSON.parse(config.customParameters);
tokenRequest.prompt = config.prompt;
tokenRequest.loginHint = config.loginHint;

myMSALObj = new msal.PublicClientApplication(msalConfig);
// Register Callbacks for Redirect flow and record the task so we
// can await its completion in the login API

redirectHandlerTask = myMSALObj.handleRedirectPromise();
}
function init(config) {
let authority;
if (config.customAuthorizationUrl) {
authority = deriveAuthorityFromAuthorizationUrl(config.customAuthorizationUrl);
} else {
authority = config.isB2C ? "https://" + config.tenant + ".b2clogin.com/tfp/" + config.tenant + ".onmicrosoft.com/" + config.policy + "/" : "https://login.microsoftonline.com/" + config.tenant;
}

const isCustomDomain = !authority.includes('microsoftonline.com') &&
!authority.includes('b2clogin.com');

const knownAuthorities = isCustomDomain
? [new URL(authority).host]
: [config.tenant + ".b2clogin.com", "login.microsoftonline.com"];

var authData = {
clientId: config.clientId,
authority: authority,
knownAuthorities: knownAuthorities,
redirectUri: config.redirectUri,
};
var postLogoutRedirectUri = {
postLogoutRedirectUri: config.postLogoutRedirectUri,
};
var msalConfig = {
auth: config?.postLogoutRedirectUri == null ? {
...authData,
} : {
...authData,
...postLogoutRedirectUri,
},
cache: {
cacheLocation: config.cacheLocation,
storeAuthStateInCookie: false,
},
};

if (typeof config.scope === "string") {
tokenRequest.scopes = config.scope.split(" ");
} else {
tokenRequest.scopes = config.scope;
}

tokenRequest.extraQueryParameters = JSON.parse(config.customParameters);
tokenRequest.prompt = config.prompt;
tokenRequest.loginHint = config.loginHint;

myMSALObj = new msal.PublicClientApplication(msalConfig);
// Register Callbacks for Redirect flow and record the task so we
// can await its completion in the login API

redirectHandlerTask = myMSALObj.handleRedirectPromise();
}

// Tries to silently acquire a token. Will return null if a token
// could not be acquired or if no cached account credentials exist.
Expand Down
22 changes: 20 additions & 2 deletions lib/aad_oauth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,27 @@ import 'model/config.dart';

/// Authenticates a user with Azure Active Directory using OAuth2.0.
class AadOAuth {
final CoreOAuth _coreOAuth;
CoreOAuth _coreOAuth;
Config _config;

AadOAuth(Config config) : _coreOAuth = CoreOAuth.fromConfig(config);
AadOAuth(Config config)
: _coreOAuth = CoreOAuth.fromConfig(config),
_config = config;

/// Changes dynamically language displayed in the login/register form
void setLanguage(String languageCode) {
const localesKey = 'ui_locales';

final updatedParameters = Map.of(_config.customParameters);
updatedParameters[localesKey] = languageCode;

final updatedConfig = _config.copyWith(
customParameters: updatedParameters,
);

_config = updatedConfig;
_coreOAuth = CoreOAuth.fromConfig(_config);
}

/// Perform Azure AD login.
///
Expand Down
11 changes: 7 additions & 4 deletions lib/helper/auth_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ class AuthStorage {
final String _tokenIdentifier;
final Token emptyToken = Token();

AuthStorage(
{String tokenIdentifier = 'Token', required AndroidOptions aOptions})
: _tokenIdentifier = tokenIdentifier,
_secureStorage = FlutterSecureStorage(aOptions: aOptions);
AuthStorage({
String tokenIdentifier = 'Token',
required AndroidOptions aOptions,
required IOSOptions iOptions,
}) : _tokenIdentifier = tokenIdentifier,
_secureStorage =
FlutterSecureStorage(aOptions: aOptions, iOptions: iOptions);

Future<void> saveTokenToCache(Token token) async {
var data = Token.toJsonMap(token);
Expand Down
6 changes: 3 additions & 3 deletions lib/helper/mobile_oauth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class MobileOAuth extends CoreOAuth {
/// [config] Parameters according to official Microsoft Documentation.
MobileOAuth(Config config)
: _authStorage = AuthStorage(
tokenIdentifier: config.tokenIdentifier,
aOptions: config.aOptions,
),
tokenIdentifier: config.tokenIdentifier,
aOptions: config.aOptions,
iOptions: config.iOptions),
_requestCode = RequestCode(config),
_requestToken = RequestToken(config);

Expand Down
6 changes: 6 additions & 0 deletions lib/model/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ class Config {
/// android storage options for shared preferences - defaults to encrypting shared prefs
AndroidOptions aOptions;

/// ios storage options for secure storage
IOSOptions iOptions;

/// Cache location used when authenticating with a web client.
/// "CacheLocation.localStorage" - Local browser storage (default)
/// "CacheLocation.sessionStorage" - Session context
Expand Down Expand Up @@ -217,6 +220,7 @@ class Config {
this.isStub = false,
this.loader = const SizedBox(),
AndroidOptions? aOptions,
this.iOptions = IOSOptions.defaultOptions,
CacheLocation? cacheLocation,
required this.navigatorKey,
this.origin,
Expand Down Expand Up @@ -269,6 +273,7 @@ class Config {
bool? isStub,
Widget? loader,
AndroidOptions? aOptions,
IOSOptions? iOptions,
CacheLocation? cacheLocation,
GlobalKey<NavigatorState>? navigatorKey,
String? origin,
Expand Down Expand Up @@ -307,6 +312,7 @@ class Config {
isStub: isStub ?? this.isStub,
loader: loader ?? this.loader,
aOptions: aOptions ?? this.aOptions,
iOptions: iOptions ?? this.iOptions,
cacheLocation: cacheLocation ?? this.cacheLocation,
navigatorKey: navigatorKey ?? this.navigatorKey,
origin: origin ?? this.origin,
Expand Down
10 changes: 5 additions & 5 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ environment:
dependencies:
flutter:
sdk: flutter
flutter_secure_storage: ^9.0.0
webview_flutter: ^4.4.1
flutter_secure_storage: ^9.2.4
webview_flutter: ^4.13.0
js: ^0.6.7
http: ^1.1.0
shared_preferences: ^2.2.1
http: ^1.5.0
shared_preferences: ^2.5.3
dartz: ^0.10.1
equatable: ^2.0.5
equatable: ^2.0.7

dev_dependencies:
flutter_test:
Expand Down