diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..a971dfb32 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[report] +include = security_monkey/*.py + diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..1750cd364 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git +secmonkey.env +boto.cfg +.travis.yml +#docs +supervisor +config-default.py +generate-docs.py diff --git a/.gitignore b/.gitignore index 18a7937b3..2de573b06 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,8 @@ devlog/ venv/ .idea/ +boto.cfg +secmonkey.env +*.crt +*.key + diff --git a/.travis.yml b/.travis.yml index 450584f32..5b5e3db54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -sudo: false +sudo: required language: python @@ -20,18 +20,28 @@ env: install: +before_install: + # - sudo apt-get -qq update + # - sudo apt-get install -y libxml2-dev libxmlsec1-dev + before_script: - psql -c "CREATE DATABASE securitymonkeydb;" -U postgres - psql -c "CREATE ROLE securitymonkeyuser LOGIN PASSWORD 'securitymonkeypass';" -U postgres - psql -c "CREATE SCHEMA securitymonkeydb GRANT Usage, Create ON SCHEMA securitymonkeydb TO securitymonkeyuser;" -U postgres - psql -c "set timezone TO 'GMT';" -U postgres - python setup.py develop + - pip install .[tests] + - pip install coveralls - python manage.py db upgrade script: - sh env_tests/test_dart.sh - - py.test security_monkey/tests || exit 1 + - coverage run -m py.test security_monkey/tests || exit 1 + +after_success: + - coveralls notifications: email: - mgrima@netflix.com + - mgrima@netflix.com + - pkelley@netflix.com diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..2959018a7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ + +# Copyright 2014 Netflix, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM ubuntu:14.04 +MAINTAINER Netflix Open Source Development + +ENV SECURITY_MONKEY_VERSION=v0.8.0 \ + SECURITY_MONKEY_SETTINGS=/usr/local/src/security_monkey/env-config/config-docker.py + +RUN apt-get update &&\ + apt-get -y -q install python-software-properties software-properties-common postgresql-9.3 postgresql-client-9.3 postgresql-contrib-9.3 curl &&\ + apt-get install -y python-pip python-dev python-psycopg2 libffi-dev libpq-dev libyaml-dev libxml2-dev libxmlsec1-dev git sudo swig &&\ + rm -rf /var/lib/apt/lists/* + +RUN pip install setuptools --upgrade + +RUN cd /usr/local/src &&\ +# git clone --branch $SECURITY_MONKEY_VERSION https://github.com/Netflix/security_monkey.git + /bin/mkdir -p security_monkey +ADD . /usr/local/src/security_monkey + +RUN cd /usr/local/src/security_monkey &&\ + python setup.py install &&\ + /bin/mkdir -p /var/log/security_monkey/ + +RUN chmod +x /usr/local/src/security_monkey/docker/*.sh &&\ + mkdir -pv /var/log/security_monkey &&\ + /usr/bin/touch /var/log/security_monkey/securitymonkey.log + # ln -s /dev/stdout /var/log/security_monkey/securitymonkey.log + +WORKDIR /usr/local/src/security_monkey +EXPOSE 5000 + +ENTRYPOINT ["/usr/local/src/security_monkey/docker/api-start.sh"] diff --git a/README.rst b/README.rst index 0f070eea2..33a72ce09 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,28 @@ .. image:: https://badge.waffle.io/Netflix/security_monkey.png?label=ready&title=Ready - :target: https://waffle.io/Netflix/security_monkey - :alt: 'Stories in Ready' + :target: https://waffle.io/Netflix/security_monkey + :alt: 'Stories in Ready' + +.. image:: https://badges.gitter.im/Join%20Chat.svg + :alt: Join the chat at https://gitter.im/Netflix/security_monkey + :target: https://gitter.im/Netflix/security_monkey?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge + +**develop branch**: + +.. image:: https://travis-ci.org/Netflix/security_monkey.svg?branch=develop + :target: https://travis-ci.org/Netflix/security_monkey + +.. image:: https://coveralls.io/repos/github/Netflix/security_monkey/badge.svg?branch=develop + :target: https://coveralls.io/github/Netflix/security_monkey + +**master branch**: + +.. image:: https://travis-ci.org/Netflix/security_monkey.svg?branch=master + :target: https://travis-ci.org/Netflix/security_monkey + +.. image:: https://coveralls.io/repos/github/Netflix/security_monkey/badge.svg?branch=master + :target: https://coveralls.io/github/Netflix/security_monkey + + *************** Security Monkey *************** @@ -16,9 +38,3 @@ Project resources - `Documentation `_ - `Source code `_ - `Issue tracker `_ - - - -.. image:: https://badges.gitter.im/Join%20Chat.svg - :alt: Join the chat at https://gitter.im/Netflix/security_monkey - :target: https://gitter.im/Netflix/security_monkey?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge \ No newline at end of file diff --git a/dart/lib/component/account_view_component/account_view_component.dart b/dart/lib/component/account_view_component/account_view_component.dart index d556b6c97..0ffc9ea42 100644 --- a/dart/lib/component/account_view_component/account_view_component.dart +++ b/dart/lib/component/account_view_component/account_view_component.dart @@ -12,22 +12,33 @@ class AccountViewComponent implements ScopeAware { Account account; bool create = false; bool _as_loaded = false; + bool _cfg_loaded = false; bool _is_error = false; String err_message = ""; + AccountConfig config; ObjectStore store; AccountViewComponent(this.routeProvider, this.router, this.store) { this.store = store; // If the URL has an ID, then let's view/edit if (routeProvider.parameters.containsKey("accountid")) { - store.one(Account, routeProvider.parameters['accountid']).then((Account account) { + store.one(Account, routeProvider.parameters['accountid']).then((account) { this.account = account; - _as_loaded = true; + this._as_loaded = true; + }); + store.one(AccountConfig, "all").then((account_config) { + this.config = account_config; + _cfg_loaded = true; }); create = false; } else { // If the URL does not have an ID, then let's create - account = new Account(); + this.account = new Account(); + store.one(AccountConfig, "all").then((account_config) { + this.config = account_config; + _cfg_loaded = true; + }); + _as_loaded = true; create = true; } } @@ -36,7 +47,7 @@ class AccountViewComponent implements ScopeAware { scope.on("globalAlert").listen(this._showMessage); } - get isLoaded => create || _as_loaded; + get isLoaded => _as_loaded && _cfg_loaded; get isError => _is_error; void _showMessage(ScopeEvent event) { @@ -53,7 +64,9 @@ class AccountViewComponent implements ScopeAware { }); }); } else { - this.store.update(this.account); + this.store.update(this.account).then((_) { + window.location.reload(); + }); } } diff --git a/dart/lib/component/account_view_component/account_view_component.html b/dart/lib/component/account_view_component/account_view_component.html index c46615fc7..f876ecc7a 100644 --- a/dart/lib/component/account_view_component/account_view_component.html +++ b/dart/lib/component/account_view_component/account_view_component.html @@ -26,26 +26,29 @@

Create Account

-
- +
- +
-
- +
+
- + +
diff --git a/dart/lib/component/item_table_component/item_table_component.dart b/dart/lib/component/item_table_component/item_table_component.dart index c7ce2d31d..1bf1e1c2f 100644 --- a/dart/lib/component/item_table_component/item_table_component.dart +++ b/dart/lib/component/item_table_component/item_table_component.dart @@ -31,6 +31,8 @@ class ItemTableComponent extends PaginatedTable implements DetachAware { 'arns': '', 'active': null, 'searchconfig': null, + 'min_score': null, + 'min_unjustified_score': null, 'page': '1', 'count': '25' }; diff --git a/dart/lib/component/itemdetails/itemdetails.html b/dart/lib/component/itemdetails/itemdetails.html index 0c0e9bed0..15d5178c2 100644 --- a/dart/lib/component/itemdetails/itemdetails.html +++ b/dart/lib/component/itemdetails/itemdetails.html @@ -78,7 +78,14 @@
{{issue.issue}} {{issue.score}} - {{issue.notes}} + Related to: +
+ + {{issue.notes}} +
+
Min Total Score
+ +
+ +
+
Min Unjustified Score
+ +
+
Status
+ + +
+
+
+ + + + diff --git a/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.dart b/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.dart new file mode 100644 index 000000000..25b5a156b --- /dev/null +++ b/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.dart @@ -0,0 +1,49 @@ +part of security_monkey; + +@Component( + selector: 'whitelist-cmp', + templateUrl: 'packages/security_monkey/component/settings/network_whitelist_component/network_whitelist_component.html', + //cssUrl: const ['/css/bootstrap.min.css'] + useShadowDom: false +) +class NetworkWhitelistComponent extends PaginatedTable { + UsernameService us; + Router router; + List cidrs; + ObjectStore store; + + NetworkWhitelistComponent(this.router, this.store, this.us) { + cidrs = new List(); + list(); + } + + get signed_in => us.signed_in; + + void list() { + store.list(NetworkWhitelistEntry, params: { + "count": ipp_as_int, + "page": currentPage + }).then((cidrs) { + super.setPaginationData(cidrs.meta); + this.cidrs = cidrs; + super.is_loaded = true; + }); + } + + void createWhitelist() { + router.go('createwhitelist', {}); + } + + void deleteWhitelist(NetworkWhitelistEntry cidr){ + store.delete(cidr).then( (_) { + store.list(NetworkWhitelistEntry).then( (cidrs) { + this.cidrs = cidrs; + }); + }); + } + + String url_encode(input) => param_to_url(input); + + get isLoaded => super.is_loaded; + get isError => super.is_error; +} diff --git a/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.html b/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.html new file mode 100644 index 000000000..b11c4bf6e --- /dev/null +++ b/dart/lib/component/settings/network_whitelist_component/network_whitelist_component.html @@ -0,0 +1,53 @@ +
+
+
Network Whitelist {{ items_displayed() }} of {{ totalItems }}
+
+

Loading . . .

+
+ {{err_message}} +
+
+
+ + + + + + + + + + + + + + +
Network NameCIDRNotes
{{cidr.name}}{{cidr.name}}{{cidr.cidr}}{{cidr.notes}}
+
+ +
+
diff --git a/dart/lib/component/settings_component/settings_component.dart b/dart/lib/component/settings_component/settings_component.dart index cf7a7bd1f..c2ff1b5eb 100644 --- a/dart/lib/component/settings_component/settings_component.dart +++ b/dart/lib/component/settings_component/settings_component.dart @@ -10,35 +10,24 @@ class SettingsComponent extends PaginatedTable { UsernameService us; Router router; List accounts; - List cidrs; - List ignorelist; List auditorlist; ObjectStore store; UserSetting user_setting; - + SettingsComponent(this.router, this.store, this.us) { - cidrs = new List(); accounts = new List(); store.customQueryOne(UserSetting, new CustomRequestParams(method: "GET", url: "$API_HOST/settings", withCredentials: true)).then((user_setting) { this.user_setting = user_setting; list(); }); - store.list(NetworkWhitelistEntry).then( (cidrs) { - this.cidrs = cidrs; - }); - - store.list(IgnoreEntry).then( (ignoreItems) { - this.ignorelist = ignoreItems; - }); - store.list(AuditorSetting).then( (auditorItems) { this.auditorlist = auditorItems; }); } - + get signed_in => us.signed_in; - + void list() { store.list(Account, params: { "count": ipp_as_int, @@ -104,30 +93,6 @@ class SettingsComponent extends PaginatedTable { router.go('createaccount', {}); } - void createWhitelist() { - router.go('createwhitelist', {}); - } - - void deleteWhitelist(NetworkWhitelistEntry cidr){ - store.delete(cidr).then( (_) { - store.list(NetworkWhitelistEntry).then( (cidrs) { - this.cidrs = cidrs; - }); - }); - } - - void createIgnoreEntry() { - router.go('createignoreentry', {}); - } - - void deleteIgnoreList(ignoreitem) { - store.delete(ignoreitem).then( (_) { - store.list(IgnoreEntry).then( (ignoreitems) { - this.ignorelist = ignoreitems; - }); - }); - } - void disableAuditor(auditor) { auditor.disabled = true; store.update(auditor); @@ -137,7 +102,7 @@ class SettingsComponent extends PaginatedTable { auditor.disabled = false; store.update(auditor); } - + String url_encode(input) => param_to_url(input); get isLoaded => super.is_loaded; diff --git a/dart/lib/component/settings_component/settings_component.html b/dart/lib/component/settings_component/settings_component.html index 1a5890738..3aaeaf0e1 100644 --- a/dart/lib/component/settings_component/settings_component.html +++ b/dart/lib/component/settings_component/settings_component.html @@ -51,8 +51,8 @@
Daily Email
Active Third Party Name - S3 Name - Account Number + Type + Identifier Notes @@ -68,8 +68,8 @@
Daily Email
{{account.name}} {{account.name}} - {{account.s3_name}} - {{account.number}} + {{account.account_type}} + {{account.identifier}} {{account.notes}} @@ -107,59 +107,11 @@
Daily Email

-
-
-
Network Whitelist {{cidrs.length}} of {{cidrs.length}}
-
-

Loading . . .

-
-
- - - - - - - - - - - - - - -
Network NameCIDRNotes
{{cidr.name}}{{cidr.name}}{{cidr.cidr}}{{cidr.notes}}
-
-
-
+

-
-
-
Ignore List {{ignorelist.length}} of {{ignorelist.length}}
-
-

Loading . . .

-
-
- - - - - - - - - - - - - - -
PrefixNotesTechnology
{{ignoreitem.prefix}}{{ignoreitem.prefix}}{{ignoreitem.notes}}{{ignoreitem.technology}}
-
-
-
+

diff --git a/dart/lib/model/Account.dart b/dart/lib/model/Account.dart index 76c22afd0..945e6e49a 100644 --- a/dart/lib/model/Account.dart +++ b/dart/lib/model/Account.dart @@ -5,12 +5,12 @@ import 'dart:convert'; class Account { int id; String name; - String s3_name; - String number; + String identifier; String notes; - String role_name; bool _active; bool _third_party; + String account_type; + Map custom_field_values = new Map(); Account(); @@ -36,10 +36,15 @@ class Account { active = data['active']; third_party = data['third_party']; name = data['name']; - s3_name = data['s3_name']; - number = data['number']; + identifier = data['identifier']; notes = data['notes']; - role_name = data['role_name']; + account_type = data['account_type']; + + if (data.containsKey('custom_fields')) { + for (var field in data['custom_fields']) { + custom_field_values[field['name']] = field['value']; + } + } } String toJson() { @@ -48,10 +53,10 @@ class Account { "active": active, "third_party": third_party, "name": name, - "s3_name": s3_name, - "number": number, + "identifier": identifier, "notes": notes, - "role_name": role_name, + "account_type": account_type, + "custom_fields": custom_field_values }; return JSON.encode(objmap); } diff --git a/dart/lib/model/Issue.dart b/dart/lib/model/Issue.dart index 6c3e315ca..ce27c2140 100644 --- a/dart/lib/model/Issue.dart +++ b/dart/lib/model/Issue.dart @@ -1,6 +1,7 @@ library security_monkey.model_issue; import 'Item.dart'; +import 'ItemLink.dart'; import 'package:security_monkey/util/utils.dart' show localDateFromAPIDate; class Issue { @@ -17,6 +18,7 @@ class Issue { bool selected_for_justification; Item item; + List item_links = new List(); Issue.fromMap(Map data) { id = data['id']; @@ -36,6 +38,13 @@ class Issue { "item": data }); - + for (var item_link in data['item_links']) { + ItemLink linkObj = new ItemLink.fromMap(item_link); + item_links.add(linkObj); + } } + + get has_sub_item => this.item_links.length != 0; + + get get_links => '{{item_links.first.name}}'; } diff --git a/dart/lib/model/ItemLink.dart b/dart/lib/model/ItemLink.dart new file mode 100644 index 000000000..0eef79f76 --- /dev/null +++ b/dart/lib/model/ItemLink.dart @@ -0,0 +1,11 @@ +library security_monkey.item_link; + +class ItemLink { + int id; + String name; + + ItemLink.fromMap(Map data) { + id = data['id']; + name = data['name']; + } +} diff --git a/dart/lib/model/account_config.dart b/dart/lib/model/account_config.dart new file mode 100644 index 000000000..b21a22e4d --- /dev/null +++ b/dart/lib/model/account_config.dart @@ -0,0 +1,32 @@ +library security_monkey.account_config; + +import 'custom_field_config.dart'; + +class AccountConfig { + List account_types = new List(); + Map identifier_labels = new Map(); + Map identifier_tool_tips = new Map(); + Map> custom_fields = new Map>(); + + AccountConfig(); + + AccountConfig.fromMap(Map data) { + if (data.containsKey('custom_configs')) { + var acc_configs = data['custom_configs']; + acc_configs.forEach((k,v) => this._addToLists(k, v)); + } + } + + void _addToLists(account_type, values) { + this.account_types.add(account_type); + this.identifier_labels[account_type] = values['identifier_label']; + this.identifier_tool_tips[account_type] = values['identifier_tool_tip']; + + var list = new List(); + var field_config = values['custom_fields']; + for (var field in field_config) { + list.add(new CustomFieldConfig.fromMap(field)); + } + this.custom_fields[account_type] = list; + } +} diff --git a/dart/lib/model/custom_field_config.dart b/dart/lib/model/custom_field_config.dart new file mode 100644 index 000000000..e8575e9e1 --- /dev/null +++ b/dart/lib/model/custom_field_config.dart @@ -0,0 +1,17 @@ +library security_monkey.custom_field_config; + +class CustomFieldConfig { + String name; + String label; + bool editable; + String tool_tip; + bool password; + + CustomFieldConfig.fromMap(Map data) { + name = data['name']; + label = data['label']; + editable = data['editable']; + tool_tip = data['tool_tip']; + password = data['password']; + } +} diff --git a/dart/lib/model/hammock_config.dart b/dart/lib/model/hammock_config.dart index bafb4f44c..40ae37fba 100644 --- a/dart/lib/model/hammock_config.dart +++ b/dart/lib/model/hammock_config.dart @@ -13,18 +13,20 @@ import 'UserSetting.dart'; import 'ignore_entry.dart'; import 'User.dart'; import 'Role.dart'; +import 'account_config.dart'; @MirrorsUsed( targets: const[ Account, IgnoreEntry, Issue, AuditorSetting, Item, ItemComment, NetworkWhitelistEntry, - Revision, RevisionComment, UserSetting, User, Role], + Revision, RevisionComment, UserSetting, User, Role, + AccountConfig], override: '*') import 'dart:mirrors'; import 'package:security_monkey/util/constants.dart'; -final serializeAWSAccount = serializer("accounts", ["id", "active", "third_party", "name", "s3_name", "number", "notes", "role_name"]); +Resource serializeAccount(Account account) => resource("accounts", account.id, account.toJson()); final serializeIssue = serializer("issues", ["id", "score", "issue", "notes", "justified", "justified_user", "justification", "justified_date", "item_id"]); final serializeRevision = serializer("revisions", ["id", "item_id", "config", "active", "date_created", "diff_html"]); final serializeItem = serializer("items", ["id", "technology", "region", "account", "name"]); @@ -63,9 +65,15 @@ createHammockConfig(Injector inj) { }, "accounts": { "type": Account, - "serializer": serializeAWSAccount, + "serializer": serializeAccount, "deserializer": { - "query": deserializeAWSAccount + "query": deserializeAccount + } + }, + "account_config": { + "type": AccountConfig, + "deserializer": { + "query": deserializeAccountConfig } }, "issues": { @@ -146,7 +154,8 @@ serializer(type, attrs) { }; } -deserializeAWSAccount(r) => new Account.fromMap(r.content); +deserializeAccount(r) => new Account.fromMap(r.content); +deserializeAccountConfig(r) => new AccountConfig.fromMap(r.content); deserializeIssue(r) => new Issue.fromMap(r.content); deserializeRevision(r) => new Revision.fromMap(r.content); deserializeItem(r) => new Item.fromMap(r.content); diff --git a/dart/lib/routing/securitymonkey_router.dart b/dart/lib/routing/securitymonkey_router.dart index 12cc42ff0..d1025aad3 100644 --- a/dart/lib/routing/securitymonkey_router.dart +++ b/dart/lib/routing/securitymonkey_router.dart @@ -4,8 +4,18 @@ import 'package:angular/angular.dart'; void securityMonkeyRouteInitializer(Router router, RouteViewFactory views) { views.configure({ + 'dashboard': ngRoute( + path: '/dashboard', + mount: { + 'view': ngRoute( + path: '', + view: 'views/dashboard.html'), + 'view_default': ngRoute( + defaultRoute: true, + view: 'views/error.html') + }), 'items': ngRoute( - path: '/items/:regions/:technologies/:accounts/:names/:arns/:active/:searchconfig/:page/:count', + path: '/items/:regions/:technologies/:accounts/:names/:arns/:active/:searchconfig/:min_score/:min_unjustified_score/:page/:count', defaultRoute: true, mount: { 'view': ngRoute( diff --git a/dart/lib/security_monkey.dart b/dart/lib/security_monkey.dart index d6ea7f32b..d8738b294 100644 --- a/dart/lib/security_monkey.dart +++ b/dart/lib/security_monkey.dart @@ -34,6 +34,9 @@ import 'model/auditorsetting.dart'; import 'model/CloudTrail.dart'; import 'model/User.dart'; import 'model/Role.dart'; +import 'model/ItemLink.dart'; +import 'model/account_config.dart'; +import 'model/custom_field_config.dart'; // Routing import 'routing/securitymonkey_router.dart'; @@ -66,7 +69,10 @@ part 'component/whitelist_view_component/whitelist_view_component.dart'; part 'component/ignore_entry_component/ignore_entry_component.dart'; part 'component/username_component/username_component.dart'; part 'component/settings/auditor_settings_component/auditor_settings_component.dart'; +part 'component/dashboard_component/dashboard_component.dart'; part 'component/settings/user_role_component/user_role_component.dart'; +part 'component/settings/network_whitelist_component/network_whitelist_component.dart'; +part 'component/settings/ignore_list_component/ignore_list_component.dart'; class SecurityMonkeyModule extends Module { @@ -100,7 +106,10 @@ class SecurityMonkeyModule extends Module { bind(IgnoreEntryComponent); bind(UsernameComponent); bind(AuditorSettingsComponent); + bind(DashboardComponent); bind(UserRoleComponent); + bind(NetworkWhitelistComponent); + bind(IgnoreListComponent); // Services bind(JustificationService); diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 057fe79ce..3987fcb17 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,6 +1,6 @@ name: security_monkey description: An AWS Policy Monitoring and Alerting Tool -version: 0.6.0 +version: 0.8.0 dependencies: angular: "^1.1.2+2" angular_ui: ">=0.6.8 <0.7.0" diff --git a/dart/web/js/sso.js b/dart/web/js/sso.js index 2e0965f79..7104ae7f9 100644 --- a/dart/web/js/sso.js +++ b/dart/web/js/sso.js @@ -13,13 +13,20 @@ $.urlParam = function(name){ var create_url = function(provider) { var next = $.urlParam("next"); var url = provider.authorizationEndpoint; - url += "?response_type="+provider.responseType; - url += "&client_id="+provider.clientId; - url += "&redirect_uri="+provider.redirectUri; - url += "&scope="+provider.scope.join(provider.scopeDelimiter); - url += "&state=clientId,"+provider.clientId+",redirectUri,"+provider.redirectUri+",return_to,"+next; - if (provider.hd) { - url += "&hd="+provider.hd; + + if (provider.name.toLowerCase() == "onelogin") { + url += "?return_to="+next; + } else { // google/ping + url += "?"; + url += "response_type="+provider.responseType; + url += "&client_id="+provider.clientId; + url += "&redirect_uri="+provider.redirectUri; + url += "&scope="+provider.scope.join(provider.scopeDelimiter); + url += "&state=clientId,"+provider.clientId+",redirectUri,"+provider.redirectUri+",return_to,"+next; + if (provider.hd) { + url += "&hd="+provider.hd; + } + } return url; }; diff --git a/dart/web/ui.html b/dart/web/ui.html index c09d2a4cd..e432fd296 100644 --- a/dart/web/ui.html +++ b/dart/web/ui.html @@ -42,25 +42,42 @@