GetProfileMappings(int portalId);
9 | ProfileMapping GetProfileMapping(string dnnProfilePropertyName, int portalId);
10 | void UpdateProfileMapping(string dnnProfilePropertyName, string aadClaimName, int portalId);
11 | void InsertProfileMapping(string dnnProfilePropertyName, string aadClaimName, int portalId);
12 | void DeleteProfileMapping(string dnnProfilePropertyName, int portalId);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/globals/application.js:
--------------------------------------------------------------------------------
1 | import utilities from "../utils";
2 | const boilerPlate = {
3 | init() {
4 | // This setting is required and define the public path
5 | // to allow the web application to download assets on demand
6 | // eslint-disable-next-line no-undef
7 | // __webpack_public_path__ = options.publicPath;
8 | let options = window.dnn.initAzureAD();
9 |
10 | utilities.init(options.utility);
11 | utilities.moduleName = options.moduleName;
12 |
13 | },
14 | dispatch() {
15 | throw new Error("dispatch method needs to be overwritten from the Redux store");
16 | }
17 | };
18 |
19 |
20 | export default boilerPlate;
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render } from "react-dom";
3 | import { Provider } from "react-redux";
4 | import configureStore from "./store/configureStore";
5 | import Root from "./containers/Root";
6 | import application from "./globals/application";
7 |
8 | let store = configureStore({enabled: false, instrumentationKey: ""});
9 |
10 | application.dispatch = store.dispatch;
11 | application.init();
12 |
13 | const appContainer = document.getElementById("azureAD-container");
14 | const initCallback = appContainer.getAttribute("data-init-callback");
15 | application.init(initCallback);
16 |
17 | render(
18 |
19 |
20 | ,
21 | appContainer
22 | );
23 |
24 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/svg/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Login.ascx:
--------------------------------------------------------------------------------
1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Login.ascx.cs" Inherits="DotNetNuke.Authentication.Azure.Login" %>
2 | <%@ Register TagPrefix="dnnC" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %>
3 |
4 |
5 |
6 |
7 |
8 | <%=LocalizeString("LoginAzure")%>
9 |
10 |
11 |
12 |
13 | <%=LocalizeString("RegisterAzure") %>
14 |
15 |
16 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/Models/RoleMapping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Caching;
3 | using DotNetNuke.ComponentModel.DataAnnotations;
4 |
5 | namespace DotNetNuke.Authentication.Azure.Components.Models
6 | {
7 | [TableName("AzureAD_RoleMappings")]
8 | //setup the primary key for table
9 | [PrimaryKey("RoleMappingId", AutoIncrement = true)]
10 | //configure caching using PetaPoco
11 | [Cacheable("RoleMapping", CacheItemPriority.Default, 20)]
12 | public class RoleMapping
13 | {
14 | public int RoleMappingId { get; set; }
15 |
16 | public string DnnRoleName { get; set; }
17 | public string AadRoleName { get; set; }
18 | public int PortalId { get; set; }
19 | public int CreatedByUserId { get; set; }
20 | public DateTime CreatedOnDate { get; set; }
21 | public int LastModifiedByUserId { get; set; }
22 | public DateTime LastModifiedOnDate { get; set; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/Models/UserMapping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Caching;
3 | using DotNetNuke.ComponentModel.DataAnnotations;
4 |
5 | namespace DotNetNuke.Authentication.Azure.Components.Models
6 | {
7 | [TableName("AzureAD_UserMappings")]
8 | //setup the primary key for table
9 | [PrimaryKey("UserMappingId", AutoIncrement = true)]
10 | //configure caching using PetaPoco
11 | [Cacheable("UserMapping", CacheItemPriority.Default, 20)]
12 | public class UserMapping
13 | {
14 | public int UserMappingId { get; set; }
15 |
16 | public string DnnPropertyName { get; set; }
17 | public string AadClaimName { get; set; }
18 | public int PortalId { get; set; }
19 | public int CreatedByUserId { get; set; }
20 | public DateTime CreatedOnDate { get; set; }
21 | public int LastModifiedByUserId { get; set; }
22 | public DateTime LastModifiedOnDate { get; set; }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/Models/ProfileMapping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Web.Caching;
3 | using DotNetNuke.ComponentModel.DataAnnotations;
4 |
5 | namespace DotNetNuke.Authentication.Azure.Components.Models
6 | {
7 | [TableName("AzureAD_ProfileMappings")]
8 | //setup the primary key for table
9 | [PrimaryKey("ProfileMappingId", AutoIncrement = true)]
10 | //configure caching using PetaPoco
11 | [Cacheable("ProfileMapping", CacheItemPriority.Default, 20)]
12 | public class ProfileMapping
13 | {
14 | public int ProfileMappingId { get; set; }
15 |
16 | public string DnnProfilePropertyName { get; set; }
17 | public string AadClaimName { get; set; }
18 | public int PortalId { get; set; }
19 | public int CreatedByUserId { get; set; }
20 | public DateTime CreatedOnDate { get; set; }
21 | public int LastModifiedByUserId { get; set; }
22 | public DateTime LastModifiedOnDate { get; set; }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/DotNetNuke.Authentication.Azure.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DotNetNuke.Authentication.Azure
5 | 4.4.5
6 | DotNetNuke.Authentication.Azure
7 | Intelequia
8 | Intelequia
9 | https://raw.githubusercontent.com/davidjrh/dnn.azureadprovider/master/LICENSE
10 | https://github.com/davidjrh/dnn.azureadprovider
11 | https://intelequia.com/favicon-32x32.png
12 | false
13 | Microsoft Entra ID Authentication provider library
14 | See https://github.com/davidjrh/dnn.azureadprovider/releases
15 | Copyright 2023
16 | Intelequia DNN AzureAD
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Providers/DataProviders/SqlDataProvider/04.03.00.SqlDataProvider:
--------------------------------------------------------------------------------
1 | /* Setup default values for new setting for separate Graph TenantId to the current tenantId */
2 |
3 | INSERT INTO {databaseOwner}[{objectQualifier}PortalSettings]
4 | (PortalID, SettingName, SettingValue, CreatedByUserID, CreatedOnDate, LastModifiedByUserID, LastModifiedOnDate, CultureCode, IsSecure)
5 | SELECT PortalID, 'Azure_AADTenantId', SettingValue, CreatedByUserID, GETUTCDATE(), LastModifiedByUserID, GETUTCDATE(), CultureCode, IsSecure
6 | FROM {databaseOwner}[{objectQualifier}PortalSettings]
7 | WHERE SettingName='Azure_TenantId'
8 |
9 | INSERT INTO {databaseOwner}[{objectQualifier}HostSettings]
10 | (SettingName, SettingValue, SettingIsSecure, CreatedByUserID, CreatedOnDate, LastModifiedByUserID, LastModifiedOnDate)
11 | SELECT 'Azure_AADTenantId', SettingValue, SettingIsSecure, CreatedByUserID, GETUTCDATE(), LastModifiedByUserID, GETUTCDATE()
12 | FROM {databaseOwner}[{objectQualifier}HostSettings]
13 | WHERE SettingName='Azure_TenantId'
14 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/constants/actionTypes/settings.js:
--------------------------------------------------------------------------------
1 | const settingsActionTypes = {
2 | SWITCH_TAB: "SWITCH_TAB",
3 | RETRIEVED_SETTINGS: "RETRIEVED_SETTINGS",
4 | UPDATED_SETTINGS: "UPDATED_SETTINGS",
5 | UPDATED_PROFILEMAPPING: "UPDATED_PROFILEMAPPING",
6 | SETTINGS_CLIENT_MODIFIED: "SETTINGS_CLIENT_MODIFIED",
7 | RETRIEVED_PROFILESETTINGS: "RETRIEVED_PROFILESETTINGS",
8 | RETRIEVED_PROFILEPROPERTIES: "RETRIEVED_PROFILEPROPERTIES",
9 | CANCELLED_PROFILEMAPPING_CLIENT_MODIFIED: "CANCELLED_PROFILEMAPPING_CLIENT_MODIFIED",
10 | PROFILEMAPPINGS_CLIENT_MODIFIED: "PROFILEMAPPINGS_CLIENT_MODIFIED",
11 | SWITCH_MAPPING_SUBTAB: "SWITCH_MAPPING_SUBTAB",
12 | RETRIEVED_ROLEMAPPINGSETTINGS: "RETRIEVED_ROLEMAPPINGSETTINGS",
13 | RETRIEVED_AVAILABLEROLES: "RETRIEVED_AVAILABLEROLES",
14 | ROLEMAPPINGS_CLIENT_MODIFIED: "ROLEMAPPINGS_CLIENT_MODIFIED",
15 | RETRIEVED_USERMAPPINGSETTINGS: "RETRIEVED_USERMAPPINGSETTINGS",
16 | USERMAPPINGS_CLIENT_MODIFIED: "USERMAPPINGS_CLIENT_MODIFIED"
17 | };
18 | export default settingsActionTypes;
--------------------------------------------------------------------------------
/docs/images/DNNAzureAD_LatestRelease.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | release
14 | release
15 | v4.5.0
16 | v4.5.0
17 |
18 |
19 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/module.css:
--------------------------------------------------------------------------------
1 | ul.buttonList .azure a span {
2 | padding-left: 45px;
3 | background: url('images/azure-login.png') no-repeat 6px 7px;
4 | }
5 | ul.buttonList .azure a:after {
6 | position: absolute;
7 | left: 35px;
8 | top: 0;
9 | height: 100%;
10 | width: 0;
11 | content: "";
12 | border-left: 1px solid rgba(0,0,0,0.2);
13 | border-right: 1px solid rgba(255,255,255,0.3);
14 | }
15 |
16 |
17 | /*AZURE*/
18 | ul.buttonList li.azure a {
19 | background: #00abec url(images/azure-bg.png) repeat-x;
20 | }
21 | ul.buttonList .azure a {
22 | color: #fff;
23 | text-shadow: 0px -1px 0px rgba(0,0,0,0.4);
24 | border-color: #3d82a0; /* dark teal blue */
25 | background-position: 0;
26 | background-color: #00abec;
27 | }
28 | ul.buttonList .azure a:hover {
29 | color: #fff;
30 | border-color: #3d82a0; /* dark teal blue */
31 | text-shadow: 0px -1px 0px rgba(0,0,0,0.4);
32 | background-position: 0 -50px;
33 | background-color: #00baff;
34 | }
35 | ul.buttonList .azure a:active {
36 | background-position: 0 -100px;
37 | border-color: #3d82a0; /* dark teal blue */
38 | background-color: #2680a9;
39 | }
40 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureADLicense.txt:
--------------------------------------------------------------------------------
1 | Intelequia
2 | Copyright (c) 2010-2026 by Intelequia
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Intelequia Technologies. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "plugins": [
3 | "react"
4 | ],
5 | "env": {
6 | "browser": true,
7 | "commonjs": true
8 | },
9 | "extends": ["eslint:recommended", "plugin:react/recommended"],
10 | "settings": {
11 | "react": {
12 | "version": "16"
13 | }
14 | },
15 | "parserOptions": {
16 | "ecmaFeatures": {
17 | "jsx": true
18 | },
19 | "ecmaVersion": 2018,
20 | "sourceType": "module"
21 | },
22 | "globals": {
23 | "__": false,
24 | "Promise": false,
25 | "VERSION": false
26 | },
27 | "rules": {
28 | "semi": "error",
29 | "no-var": "error",
30 | "quotes": ["warn", "double" ],
31 | "indent": ["warn", 4, {"SwitchCase": 1}],
32 | "no-unused-vars": "warn",
33 | "no-console": "warn",
34 | "keyword-spacing": "warn",
35 | "eqeqeq": "warn",
36 | "space-before-function-paren": ["warn", { "anonymous": "always", "named": "never" }],
37 | "space-before-blocks": "warn",
38 | "no-multiple-empty-lines": "warn",
39 | "react/jsx-equals-spacing": ["warn", "never"],
40 | "id-match": ["error", "^([A-Za-z0-9_])+$", {"properties": true}]
41 | }
42 | };
43 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/general/generalSettings.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index";
2 | .dnn-azuread-generalSettings {
3 | box-sizing: border-box;
4 | padding: 35px 25px;
5 | * {
6 | box-sizing: border-box;
7 | }
8 | h1 {
9 | margin-top: 30px;
10 | margin-bottom: 15px;
11 | text-transform: uppercase;
12 | }
13 | .panel-description {
14 | margin-bottom: 30px;
15 | }
16 | .logo {
17 | float: right;
18 | background-image: url(img/AAD.png);
19 | background-repeat: no-repeat;
20 | background-size: 70px;
21 | width: 80px;
22 | height: 80px;
23 | }
24 | p {
25 | margin-bottom: 20px;
26 | }
27 | .dnn-switch-container {
28 | width: 90%;
29 | }
30 | .directory-section {
31 | margin-top: 10px;
32 | }
33 | .editor-row {
34 | display: inline-block;
35 | width: 90%;
36 | }
37 | .input-full-row {
38 | width: 95%;
39 | }
40 | .dnn-single-line-input-with-error {
41 | width: 100%;
42 | padding-bottom: 15px;
43 | }
44 | .dnn-ui-common-single-line-input.small {
45 | margin-bottom: 0px!important;
46 | }
47 | .buttons-box {
48 | margin-top: 50px;
49 | margin-bottom: 30px;
50 | button.dnn-ui-common-button[role=primary] {
51 | margin-left: 10px;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/IAadController.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2019
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | using System.Net.Http;
25 |
26 | namespace DotNetNuke.Authentication.Azure.Components
27 | {
28 | public interface IAadController
29 | {
30 | string SchemeType { get; }
31 | string ValidateToken(HttpRequestMessage request);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure.Extensibility/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DotNetNuke.Authentication.Azure.Extensibility")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Intelequia")]
12 | [assembly: AssemblyProduct("DotNetNuke.Authentication.Azure.Extensibility")]
13 | [assembly: AssemblyCopyright("Copyright © 2025")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("42445032-9098-4160-930d-4127dc292695")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.1.0")]
36 | [assembly: AssemblyFileVersion("1.0.1.0")]
37 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/Graph/GraphServiceClientFactory.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graph;
2 | using System;
3 | using System.Net.Http;
4 | using System.Net.Http.Headers;
5 | using System.Reflection;
6 | using System.Threading.Tasks;
7 |
8 | namespace DotNetNuke.Authentication.Azure.Components.Graph
9 | {
10 | internal static class GraphServiceClientFactory
11 | {
12 | public static GraphServiceClient GetAuthenticatedGraphClient(
13 | Func> acquireAccessToken)
14 | {
15 | return new GraphServiceClient(
16 | new CustomAuthenticationProvider(acquireAccessToken)
17 | );
18 | }
19 | }
20 |
21 | class CustomAuthenticationProvider : IAuthenticationProvider
22 | {
23 | private readonly Func> _acquireAccessToken;
24 | public CustomAuthenticationProvider(Func> acquireAccessToken)
25 | {
26 | _acquireAccessToken = acquireAccessToken;
27 | }
28 |
29 | public async Task AuthenticateRequestAsync(HttpRequestMessage requestMessage)
30 | {
31 | var accessToken = await _acquireAccessToken.Invoke();
32 |
33 | // Add the token in the Authorization header
34 | requestMessage.Headers.Authorization = new AuthenticationHeaderValue(
35 | "Bearer", accessToken
36 | );
37 | string version = CustomAttributeExtensions.GetCustomAttribute((Assembly.GetExecutingAssembly()))?.Version;
38 | requestMessage.Headers.Add("User-Agent", $"DNN Azure AD Provider (v{version})");
39 | }
40 |
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/roleMappings/roleMappingEditor/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .rolemapping-editor {
3 | float: left;
4 | margin: 20px 30px;
5 | .topMessage {
6 | border: 1px solid @alto;
7 | padding: 10px 20px;
8 | background-color: @mercury;
9 | margin: 0 0 20px 0;
10 | }
11 | .dnn-ui-common-input-group {
12 | padding: 0 0 15px 0;
13 | label {
14 | font-weight: bolder;
15 | float: left;
16 | }
17 | .dnn-label {
18 | margin: 8px 0;
19 | }
20 | .dnn-dropdown,.dnn-dropdown-with-error
21 | {
22 | width: 100% !important;
23 | box-sizing: border-box;
24 | }
25 | .dnn-single-line-input-with-error {
26 | width: 100% !important;
27 | }
28 | }
29 | .dnn-grid-system {
30 | .left-column {
31 | padding-right: 30px;
32 | border-right: 1px solid @alto;
33 | }
34 | .right-column {
35 | padding-left: 30px;
36 | border-left: 0 !important;
37 | }
38 | }
39 | .editor-buttons-box {
40 | width: 100%;
41 | text-align: center;
42 | float: left;
43 | margin: 30px 0 0 0;
44 | .dnn-ui-common-button {
45 | margin: 5px;
46 | }
47 | .edit-icon {
48 | margin: 0px 10px 20px 10px;
49 | float: right;
50 | svg {
51 | width: 16px;
52 | float: left;
53 | height: 16px;
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/userMappingEditor/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .usermapping-editor {
3 | float: left;
4 | margin: 20px 30px;
5 | .topMessage {
6 | border: 1px solid @alto;
7 | padding: 10px 20px;
8 | background-color: @mercury;
9 | margin: 0 0 20px 0;
10 | }
11 | .dnn-ui-common-input-group {
12 | padding: 0 0 15px 0;
13 | label {
14 | font-weight: bolder;
15 | float: left;
16 | }
17 | .dnn-label {
18 | margin: 8px 0;
19 | }
20 | .dnn-dropdown,.dnn-dropdown-with-error
21 | {
22 | width: 100% !important;
23 | box-sizing: border-box;
24 | }
25 | .dnn-single-line-input-with-error {
26 | width: 100% !important;
27 | }
28 | }
29 | .dnn-grid-system {
30 | .left-column {
31 | padding-right: 30px;
32 | border-right: 1px solid @alto;
33 | }
34 | .right-column {
35 | padding-left: 30px;
36 | border-left: 0 !important;
37 | }
38 | }
39 | .editor-buttons-box {
40 | width: 100%;
41 | text-align: center;
42 | float: left;
43 | margin: 30px 0 0 0;
44 | .dnn-ui-common-button {
45 | margin: 5px;
46 | }
47 | .edit-icon {
48 | margin: 0px 10px 20px 10px;
49 | float: right;
50 | svg {
51 | width: 16px;
52 | float: left;
53 | height: 16px;
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/profileMappings/profileMappingEditor/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .profilemapping-editor {
3 | float: left;
4 | margin: 20px 30px;
5 | .topMessage {
6 | border: 1px solid @alto;
7 | padding: 10px 20px;
8 | background-color: @mercury;
9 | margin: 0 0 20px 0;
10 | }
11 | .dnn-ui-common-input-group {
12 | padding: 0 0 15px 0;
13 | label {
14 | font-weight: bolder;
15 | float: left;
16 | }
17 | .dnn-label {
18 | margin: 8px 0;
19 | }
20 | .dnn-dropdown,.dnn-dropdown-with-error
21 | {
22 | width: 100% !important;
23 | box-sizing: border-box;
24 | }
25 | .dnn-single-line-input-with-error {
26 | width: 100% !important;
27 | }
28 | }
29 | .dnn-grid-system {
30 | .left-column {
31 | padding-right: 30px;
32 | border-right: 1px solid @alto;
33 | }
34 | .right-column {
35 | padding-left: 30px;
36 | border-left: 0 !important;
37 | }
38 | }
39 | .editor-buttons-box {
40 | width: 100%;
41 | text-align: center;
42 | float: left;
43 | margin: 30px 0 0 0;
44 | .dnn-ui-common-button {
45 | margin: 5px;
46 | }
47 | .edit-icon {
48 | margin: 0px 10px 20px 10px;
49 | float: right;
50 | svg {
51 | width: 16px;
52 | float: left;
53 | height: 16px;
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/advanced/advancedSettings.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index";
2 | .dnn-azuread-aad-advancedSettings {
3 | box-sizing: border-box;
4 | padding: 35px 25px;
5 | * {
6 | box-sizing: border-box;
7 | }
8 | h1 {
9 | margin-top: 10px;
10 | margin-bottom: 10px;
11 | text-transform: uppercase;
12 | }
13 | p {
14 | margin-bottom: 20px;
15 | }
16 | .dnn-switch-container {
17 | width: 90%;
18 | }
19 | .editor-row {
20 | display: inline-block;
21 | width: 90%;
22 | }
23 | .dnn-single-line-input-with-error {
24 | width: 100%;
25 | padding-bottom: 15px;
26 | }
27 | .dnn-ui-common-single-line-input.small {
28 | margin-bottom: 0px!important;
29 | }
30 | .dnn-dropdown-with-error {
31 | width: 90%;
32 | }
33 | .buttons-box {
34 | margin-top: 50px;
35 | margin-bottom: 30px;
36 | button.dnn-ui-common-button[role=primary] {
37 | margin-left: 10px;
38 | }
39 | }
40 | .warning-container {
41 | width: 100%;
42 | float: left;
43 | margin: 10px 0 15px 0;
44 | font-weight: bolder;
45 | color: @alizarinCrimson;
46 | .collapsible-content {
47 | margin-top: 5px;
48 | > div {
49 | border: solid 1px;
50 | }
51 | }
52 | .warning-icon {
53 | > svg {
54 | width: 17px;
55 | float: left;
56 | height: 17px;
57 | margin: 0 10px 0 0;
58 | }
59 | }
60 | .warning-msg {
61 | margin-left: 30px;
62 | }
63 | }
64 | h1.spacer {
65 | margin-top: 25px;
66 | }
67 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Logoff.ascx.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2010-2017
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | #region Usings
25 |
26 | using System;
27 | using DotNetNuke.Authentication.Azure.Components;
28 | using DotNetNuke.Services.Authentication;
29 |
30 | #endregion
31 |
32 | namespace DotNetNuke.Authentication.Azure
33 | {
34 | public partial class Logoff : AuthenticationLogoffBase
35 | {
36 | protected override void OnInit(EventArgs e)
37 | {
38 | base.OnInit(e);
39 | var oauthClient = new AzureClient(PortalId, AuthMode.Login);
40 | oauthClient.Logout();
41 | OnLogOff(e);
42 | OnRedirect(e);
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Login.ascx.designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | namespace DotNetNuke.Authentication.Azure {
11 |
12 |
13 | public partial class Login {
14 |
15 | ///
16 | /// AzureCss control.
17 | ///
18 | ///
19 | /// Auto-generated field.
20 | /// To modify move field declaration from designer file to code-behind file.
21 | ///
22 | // protected global::DotNetNuke.Web.Client.ClientResourceManagement.DnnCssInclude AzureCss;
23 |
24 | ///
25 | /// loginItem control.
26 | ///
27 | ///
28 | /// Auto-generated field.
29 | /// To modify move field declaration from designer file to code-behind file.
30 | ///
31 | protected global::System.Web.UI.HtmlControls.HtmlGenericControl loginItem;
32 |
33 | ///
34 | /// loginButton control.
35 | ///
36 | ///
37 | /// Auto-generated field.
38 | /// To modify move field declaration from designer file to code-behind file.
39 | ///
40 | protected global::System.Web.UI.WebControls.LinkButton loginButton;
41 |
42 | ///
43 | /// registerItem control.
44 | ///
45 | ///
46 | /// Auto-generated field.
47 | /// To modify move field declaration from designer file to code-behind file.
48 | ///
49 | protected global::System.Web.UI.HtmlControls.HtmlGenericControl registerItem;
50 |
51 | ///
52 | /// registerButton control.
53 | ///
54 | ///
55 | /// Auto-generated field.
56 | /// To modify move field declaration from designer file to code-behind file.
57 | ///
58 | protected global::System.Web.UI.WebControls.LinkButton registerButton;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Settings.ascx.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2010-2017
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | #region Usings
25 |
26 | using System;
27 | using DotNetNuke.Authentication.Azure.Components;
28 | using DotNetNuke.Services.Authentication.OAuth;
29 |
30 | #endregion
31 |
32 | namespace DotNetNuke.Authentication.Azure
33 | {
34 | public partial class Settings : OAuthSettingsBase
35 | {
36 | protected override string AuthSystemApplicationName => "Azure";
37 |
38 | public override void UpdateSettings()
39 | {
40 | if (SettingsEditor.IsValid && SettingsEditor.IsDirty)
41 | {
42 | var config = (AzureConfig)SettingsEditor.DataSource;
43 | AzureConfig.UpdateConfig(config);
44 | }
45 | }
46 |
47 | protected override void OnLoad(EventArgs e)
48 | {
49 | base.OnLoad(e);
50 | OAuthConfigBase.ClearConfig(AuthSystemApplicationName, PortalId);
51 | var config = AzureConfig.GetConfig(AuthSystemApplicationName, PortalId);
52 | SettingsEditor.DataSource = config;
53 | SettingsEditor.DataBind();
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Services/Hello.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2019
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | using DotNetNuke.Web.Api;
25 | using System;
26 | using System.Net;
27 | using System.Net.Http;
28 | using System.Web.Http;
29 |
30 |
31 | namespace DotNetNuke.Authentication.Azure.Services
32 | {
33 | public class RouterMapper : IServiceRouteMapper
34 | {
35 | public void RegisterRoutes(IMapRoute mapRouteManager)
36 | {
37 | mapRouteManager.MapHttpRoute("DotNetNuke.Authentication.Azure.Services", "default", "{controller}/{action}", new[] { "DotNetNuke.Authentication.Azure.Services" });
38 | }
39 | }
40 |
41 | public class HelloController : DnnApiController
42 | {
43 | [HttpGet]
44 | [DnnAuthorize(AuthTypes = "JWT")]
45 | public HttpResponseMessage Test()
46 | {
47 | try
48 | {
49 | return Request.CreateResponse(HttpStatusCode.OK, $"Hello {UserInfo.DisplayName}");
50 | }
51 | catch (Exception ex)
52 | {
53 | return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dnn-azure-ad",
3 | "version": "4.2.0",
4 | "private": true,
5 | "description": "DNN Azure AD persona bar settings",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/davidjrh/dnn.azureadprovider.git"
9 | },
10 | "license": "MIT",
11 | "keywords": [
12 | "DNN",
13 | "React",
14 | "DNN Module",
15 | "Persona Bar",
16 | "Intelequia",
17 | "Azure AD",
18 | "Office 365"
19 | ],
20 | "scripts": {
21 | "build": "set NODE_ENV=production&&webpack --mode production",
22 | "test": "jest",
23 | "test:watch": "jest --watch",
24 | "debug": "set NODE_ENV=debug&&webpack -p",
25 | "webpack": "webpack-dev-server --mode development --host localhost --port 8080 --hot --history-api-fallback",
26 | "watch": "set NODE_ENV=debug & webpack --mode=development --progress --colors --watch",
27 | "analyze": "set NODE_ENV=production&&webpack -p --json | webpack-bundle-size-analyzer",
28 | "lint": "eslint --fix"
29 | },
30 | "devDependencies": {
31 | "@babel/core": "^7.1.6",
32 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
33 | "@babel/plugin-transform-react-jsx": "^7.2.0",
34 | "@babel/preset-env": "^7.1.6",
35 | "@babel/preset-react": "^7.0.0",
36 | "@dnnsoftware/dnn-react-common": "9.11.0",
37 | "array.prototype.find": "2.0.4",
38 | "array.prototype.findindex": "2.0.2",
39 | "babel-loader": "^8.0.6",
40 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
41 | "create-react-class": "^15.6.3",
42 | "css-loader": "2.1.1",
43 | "eslint": "7.32.0",
44 | "eslint-loader": "4.0.2",
45 | "eslint-plugin-jest": "^22.0.0",
46 | "eslint-plugin-react": "7.11.1",
47 | "eslint-plugin-spellcheck": "0.0.11",
48 | "file-loader": "3.0.1",
49 | "jest": "^28.1.2",
50 | "jwt-decode": "2.2.0",
51 | "less": "4.1.2",
52 | "less-loader": "5.0.0",
53 | "prop-types": "^15.6.2",
54 | "raw-loader": "2.0.0",
55 | "react": "^16.6.3",
56 | "react-custom-scrollbars": "4.2.1",
57 | "react-dom": "^16.6.3",
58 | "react-hot-loader": "4.8.5",
59 | "react-modal": "3.6.1",
60 | "react-redux": "^6.0.0",
61 | "redux": "^4.0.1",
62 | "redux-immutable-state-invariant": "^2.1.0",
63 | "redux-thunk": "^2.3.0",
64 | "source-map-loader": "^0.2.3",
65 | "style-loader": "^0.23.1",
66 | "url-loader": "1.1.2",
67 | "webpack": "^4.31.0",
68 | "webpack-bundle-size-analyzer": "3.0.0",
69 | "webpack-cli": "4.10.0",
70 | "webpack-dev-server": "4.11.1"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/State.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace DotNetNuke.Authentication.Azure.Components
4 | {
5 | public class State
6 | {
7 | public State()
8 | {
9 | Service = AzureConfig.ServiceName;
10 | PortalId = -1;
11 | Culture = "";
12 | RedirectUrl = "";
13 | }
14 | public State(string s)
15 | {
16 | Service = "";
17 | PortalId = -1;
18 | Culture = "";
19 | RedirectUrl = "";
20 | ParseState(s);
21 | }
22 | public string Service { get; set; }
23 | public int PortalId { get; set; }
24 | public string Culture { get; set; }
25 | public string RedirectUrl { get; set; }
26 | public bool IsUserProfile { get; set; }
27 |
28 | public override string ToString()
29 | {
30 | var s = "";
31 | if (!string.IsNullOrEmpty(Service))
32 | {
33 | s += $"s={Service}";
34 | }
35 | if (PortalId != -1)
36 | {
37 | s += $";p={PortalId}";
38 | }
39 | if (!string.IsNullOrEmpty(Culture))
40 | {
41 | s += $";c={Culture}";
42 | }
43 | if (!string.IsNullOrEmpty(RedirectUrl))
44 | {
45 | s += $";r={Uri.EscapeDataString(RedirectUrl)}";
46 | }
47 | return s;
48 | }
49 | public void ParseState(string s)
50 | {
51 | if (string.IsNullOrEmpty(s))
52 | return;
53 | var pairs = s.Split(';');
54 | foreach (var pair in pairs)
55 | {
56 | var item = pair.Split('=');
57 | if (item.Length == 2)
58 | {
59 | switch (item[0])
60 | {
61 | case "s":
62 | Service = item[1];
63 | break;
64 | case "p":
65 | PortalId = int.Parse(item[1]);
66 | break;
67 | case "c":
68 | Culture = item[1];
69 | break;
70 | case "r":
71 | RedirectUrl = Uri.UnescapeDataString(item[1]);
72 | break;
73 | default:
74 | break;
75 | }
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/.eslintskipwords.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | "dnn",
3 | "evoq",
4 | "eslint",
5 | "fetch-ie8",
6 | "react-dom",
7 | "lodash",
8 | "bool",
9 | "func",
10 | "dropdown",
11 | "globals",
12 | "init",
13 | "cors",
14 | "api",
15 | "integrations",
16 | "const",
17 | "dom",
18 | "stringify",
19 | "debounce",
20 | "debounced",
21 | "unmount",
22 | "ceil",
23 | "px",
24 | "rgba",
25 | "svg",
26 | "html",
27 | "src",
28 | "calc",
29 | "img",
30 | "jpg",
31 | "nowrap",
32 | "js",
33 | "dropzone",
34 | "ondropactivate",
35 | "ondragenter",
36 | "draggable",
37 | "ondrop",
38 | "ondragleave",
39 | "ondropdeactivate",
40 | "droppable",
41 | "onmove",
42 | "onend",
43 | "interactable",
44 | "webkit",
45 | "rect",
46 | "concat",
47 | "resize",
48 | "sortable",
49 | "socialpanelheader",
50 | "socialpanelbody",
51 | "asc",
52 | "dx",
53 | "dy",
54 | "num",
55 | "reactid",
56 | "currentcolor",
57 | "ui",
58 | "checkbox",
59 | "tooltip",
60 | "scrollbar",
61 | "unshift",
62 | "dragstart",
63 | "contenteditable",
64 | "addons",
65 | "tbody",
66 | "resizable",
67 | "resizemove",
68 | "resizestart",
69 | "resizeend",
70 | "resizing",
71 | "resized",
72 | "ondropmove",
73 | "moz",
74 | "evq",
75 | "btn",
76 | "addon",
77 | "substring",
78 | "jpeg",
79 | "gif",
80 | "pdf",
81 | "png",
82 | "ppt",
83 | "txt",
84 | "autocomplete",
85 | "utils",
86 | "js-htmlencode",
87 | "webpack",
88 | "undef",
89 | "analytics",
90 | "dataset",
91 | "checkmark",
92 | "li",
93 | "br",
94 | "localizations",
95 | "javascript",
96 | "ie",
97 | "pikaday",
98 | "na",
99 | "searchable",
100 | "clearable",
101 | "http",
102 | "decrement",
103 | "ok",
104 | "checkboxes",
105 | "ddmmyy",
106 | "mmddyy",
107 | "ddmmyyyy",
108 | "mmddyyyy",
109 | "yyyymmdd",
110 | "td",
111 | "th",
112 | "marketo",
113 | "salesforce",
114 | "captcha",
115 | "rgb",
116 | "sunday",
117 | "xxxx",
118 | "typeof",
119 | "popup",
120 | "ccc",
121 | "aaf",
122 | "dddd",
123 | "redux",
124 | "middleware",
125 | "dev",
126 | "util",
127 | "searchpanel",
128 | "uncollapse",
129 | "dev",
130 | "ctrl"
131 | ]
132 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Providers/DataProviders/SqlDataProvider/uninstall.SqlDataProvider:
--------------------------------------------------------------------------------
1 | DELETE {databaseOwner}[{objectQualifier}PortalSettings]
2 | WHERE SettingName IN
3 | (
4 | 'Azure_APIKey'
5 | , 'Azure_APISecret'
6 | , 'Azure_RedirectUri'
7 | , 'Azure_OnErrorUri'
8 | , 'Azure_TenantId'
9 | , 'Azure_AutoRedirect'
10 | , 'Azure_AutoAuthorize'
11 | , 'Azure_AutoMatchExistingUsers'
12 | , 'Azure_Enabled'
13 | , 'Azure_AADTenantId'
14 | , 'Azure_AADApplicationId'
15 | , 'Azure_AADApplicationKey'
16 | , 'Azure_GraphUseCustomParams'
17 | , 'Azure_JwtAudiences'
18 | , 'Azure_RoleSyncEnabled'
19 | , 'Azure_UserSyncEnabled'
20 | , 'Azure_ProfileSyncEnabled'
21 | , 'Azure_JwtAuthEnabled'
22 | , 'Azure_APIResource'
23 | , 'Azure_Scopes'
24 | , 'Azure_UsernamePrefixEnabled'
25 | , 'Azure_GroupNamePrefixEnabled'
26 | , 'Azure_AuthorizationCodePrompt'
27 | , 'Azure_DomainHint'
28 | , 'AzureB2C_UserGlobalSettings'
29 | )
30 | GO
31 |
32 | DELETE {databaseOwner}[{objectQualifier}HostSettings]
33 | WHERE SettingName IN
34 | (
35 | 'Azure_APIKey'
36 | , 'Azure_APISecret'
37 | , 'Azure_RedirectUri'
38 | , 'Azure_OnErrorUri'
39 | , 'Azure_TenantId'
40 | , 'Azure_AutoRedirect'
41 | , 'Azure_AutoAuthorize'
42 | , 'Azure_AutoMatchExistingUsers'
43 | , 'Azure_Enabled'
44 | , 'Azure_AADTenantId'
45 | , 'Azure_AADApplicationId'
46 | , 'Azure_AADApplicationKey'
47 | , 'Azure_GraphUseCustomParams'
48 | , 'Azure_JwtAudiences'
49 | , 'Azure_RoleSyncEnabled'
50 | , 'Azure_UserSyncEnabled'
51 | , 'Azure_ProfileSyncEnabled'
52 | , 'Azure_JwtAuthEnabled'
53 | , 'Azure_APIResource'
54 | , 'Azure_Scopes'
55 | , 'Azure_UsernamePrefixEnabled'
56 | , 'Azure_GroupNamePrefixEnabled'
57 | , 'Azure_AuthorizationCodePrompt'
58 | , 'Azure_DomainHint'
59 | , 'AzureB2C_UserGlobalSettings'
60 | )
61 | GO
62 |
63 | DELETE FROM {databaseOwner}[{objectQualifier}Schedule]
64 | WHERE TypeFullName = 'DotNetNuke.Authentication.Azure.ScheduledTasks.SyncSchedule, DotNetNuke.Authentication.Azure')
65 | GO
66 |
67 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_UserMappings]', N'U') IS NULL
68 | BEGIN
69 | DROP TABLE {databaseOwner}[{objectQualifier}AzureAD_UserMappings]
70 | END
71 |
72 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_ProfileMappings]', N'U') IS NULL
73 | BEGIN
74 | DROP TABLE {databaseOwner}[{objectQualifier}AzureAD_ProfileMappings]
75 | END
76 |
77 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_RoleMappings]', N'U') IS NULL
78 | BEGIN
79 | DROP TABLE {databaseOwner}[{objectQualifier}AzureAD_RoleMappings]
80 | END
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/FeatureController.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2019
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | using DotNetNuke.Entities.Modules;
25 | using System;
26 | using System.Linq;
27 |
28 | namespace DotNetNuke.Authentication.Azure.Components
29 | {
30 | public class FeatureController : IUpgradeable
31 | {
32 | public string UpgradeModule(string version)
33 | {
34 | try
35 | {
36 | var task = DotNetNuke.Services.Scheduling.SchedulingController.GetSchedule().FirstOrDefault(x => x.TypeFullName == "DotNetNuke.Authentication.Azure.ScheduledTasks.SyncSchedule, DotNetNuke.Authentication.Azure");
37 | if (task != null)
38 | {
39 | DotNetNuke.Services.Scheduling.SchedulingController.UpdateSchedule(task.ScheduleID,
40 | task.TypeFullName,
41 | task.TimeLapse, task.TimeLapseMeasurement, task.RetryTimeLapse, task.RetryTimeLapseMeasurement,
42 | task.RetainHistoryNum, task.AttachToEvent, task.CatchUpEnabled, true, task.ObjectDependencies,
43 | "," + Environment.MachineName + ",", task.FriendlyName);
44 | }
45 | return "Success";
46 | }
47 | catch (Exception ex)
48 | {
49 | return "Failed: " + ex.Message;
50 | }
51 | }
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/DotNetNuke.Authentication.Azure.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32901.215
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetNuke.Authentication.Azure", "DotNetNuke.Authentication.Azure.csproj", "{F5BB1B82-D843-4709-A57E-3A9CC290403F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{30168D48-BC63-47D3-9C90-75F0C902C8D2}"
9 | ProjectSection(SolutionItems) = preProject
10 | ..\.build\ModulePackage.targets = ..\.build\ModulePackage.targets
11 | ..\.build\MSBuild.Community.Tasks.targets = ..\.build\MSBuild.Community.Tasks.targets
12 | EndProjectSection
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetNuke.Authentication.Azure.Extensibility", "..\DotNetNuke.Authentication.Azure.Extensibility\DotNetNuke.Authentication.Azure.Extensibility.csproj", "{42445032-9098-4160-930D-4127DC292695}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release Legacy|Any CPU = Release Legacy|Any CPU
20 | Release|Any CPU = Release|Any CPU
21 | EndGlobalSection
22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
23 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Release Legacy|Any CPU.ActiveCfg = Release|Any CPU
26 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Release Legacy|Any CPU.Build.0 = Release|Any CPU
27 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {F5BB1B82-D843-4709-A57E-3A9CC290403F}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {42445032-9098-4160-930D-4127DC292695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {42445032-9098-4160-930D-4127DC292695}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {42445032-9098-4160-930D-4127DC292695}.Release Legacy|Any CPU.ActiveCfg = Release Legacy|Any CPU
32 | {42445032-9098-4160-930D-4127DC292695}.Release Legacy|Any CPU.Build.0 = Release Legacy|Any CPU
33 | {42445032-9098-4160-930D-4127DC292695}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {42445032-9098-4160-930D-4127DC292695}.Release|Any CPU.Build.0 = Release|Any CPU
35 | EndGlobalSection
36 | GlobalSection(SolutionProperties) = preSolution
37 | HideSolutionNode = FALSE
38 | EndGlobalSection
39 | GlobalSection(ExtensibilityGlobals) = postSolution
40 | SolutionGuid = {CF2AE640-C05D-4B31-8048-8B40EC7CD7E4}
41 | EndGlobalSection
42 | EndGlobal
43 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/admin/personaBar/scripts/AzureAD.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | define(['jquery',
3 | 'main/config',
4 | 'main/loader'
5 | ],
6 | function ($, cf, loader) {
7 | var initCallback;
8 | var utility;
9 | var settings;
10 | var config = cf.init();
11 |
12 | function loadScript(basePath) {
13 | var normalizedCulture = config.culture.split("-")[0];
14 | var language = getBundleLanguage(normalizedCulture);
15 | var url = basePath + "/bundle-" + language + ".js";
16 | $.ajax({
17 | dataType: "script",
18 | cache: true,
19 | url: url
20 | });
21 | }
22 |
23 | function getBundleLanguage(culture) {
24 | var fallbackLanguage = "en";
25 | var availableLanguages = ["en"];
26 | return availableLanguages.indexOf(culture) > 0 ? culture : fallbackLanguage;
27 | }
28 |
29 |
30 | return {
31 | init: function (wrapper, util, params, callback) {
32 | initCallback = callback;
33 | utility = util;
34 | settings = params.settings;
35 |
36 | if (!settings) {
37 | throw new Error("Azure AD settings are not defined in persona bar customSettings");
38 | }
39 |
40 | var publicPath = settings.uiUrl + "/scripts/bundles/";
41 | window.dnn.initAzureAD = function initializeAzureAD() {
42 | return {
43 | publicPath: publicPath,
44 | apiServiceUrl: settings.apiUrl,
45 | libraryVersion: settings.libraryVersion,
46 | loader: loader,
47 | utility: util,
48 | moduleName: 'AzureAD',
49 | notifier: {
50 | confirm: util.confirm,
51 | notify: util.notify,
52 | notifyError: util.notifyError
53 | }
54 | };
55 | };
56 | loadScript(publicPath);
57 |
58 | if (typeof callback === "function") {
59 | callback();
60 | }
61 | },
62 |
63 | load: function (params, callback) {
64 | var azureAD = window.dnn.azureAD;
65 | if (azureAD && azureAD.load) {
66 | azureAD.load();
67 | }
68 |
69 | if (typeof callback === "function") {
70 | callback();
71 | }
72 | }
73 | };
74 | });
75 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Services/AuthorizationController.cs:
--------------------------------------------------------------------------------
1 | using DotNetNuke.Authentication.Azure.Components;
2 | using DotNetNuke.Common;
3 | using DotNetNuke.Entities.Portals;
4 | using DotNetNuke.Web.Api;
5 | using System;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Net.Http;
9 | using System.Web.Http;
10 |
11 | namespace DotNetNuke.Authentication.Azure.Services
12 | {
13 | public class AuthorizationController : DnnApiController
14 | {
15 | [HttpGet]
16 | [AllowAnonymous]
17 | public HttpResponseMessage RedirectToPortal()
18 | {
19 | try
20 | {
21 | var stateKey = Request.GetQueryNameValuePairs()?.FirstOrDefault(x => x.Key == "state");
22 | if (stateKey == null)
23 | {
24 | return Request.CreateResponse(HttpStatusCode.BadRequest, "No state was specified");
25 | }
26 | var state = new State(stateKey.Value.Value.ToString());
27 | if (state.Service != AzureConfig.ServiceName)
28 | {
29 | return Request.CreateResponse(HttpStatusCode.BadRequest, "State not build for Azure AD");
30 | }
31 | var portalId = state.PortalId;
32 | if (portalId < 0)
33 | {
34 | return Request.CreateResponse(HttpStatusCode.BadRequest, "Not valid portal Id");
35 | }
36 | var portalAliases = PortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).Where(x => x.IsPrimary);
37 | var portalAlias = portalAliases.FirstOrDefault();
38 | if (!string.IsNullOrEmpty(state.Culture) && portalAliases.Any(x => x.CultureCode == state.Culture))
39 | {
40 | portalAlias = portalAliases.FirstOrDefault(x => x.CultureCode == state.Culture);
41 | }
42 |
43 | var portalSettings = new PortalSettings(portalId);
44 | portalSettings.PortalAlias = portalAlias;
45 | var uriBuilder = new UriBuilder(Globals.LoginURL(state.RedirectUrl, false, portalSettings));
46 | if (!Request.RequestUri.IsDefaultPort)
47 | {
48 | uriBuilder.Port = Request.RequestUri.Port;
49 | }
50 | uriBuilder.Query = !string.IsNullOrEmpty(Request.RequestUri.Query) ? Request.RequestUri.Query.Substring(1) : "";
51 |
52 | var response = Request.CreateResponse(HttpStatusCode.Redirect);
53 | response.Headers.Location = uriBuilder.Uri;
54 | return response;
55 | }
56 | catch (Exception ex)
57 | {
58 | return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/MenuController.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2010-2017
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | using System.Collections.Generic;
25 | using Dnn.PersonaBar.Library.Controllers;
26 | using Dnn.PersonaBar.Library.Model;
27 | using DotNetNuke.Entities.Portals;
28 | using DotNetNuke.Entities.Users;
29 |
30 | namespace DotNetNuke.Authentication.Azure.Components
31 | {
32 | public class MenuController : IMenuItemController
33 | {
34 | public void UpdateParameters(MenuItem menuItem)
35 | {
36 | }
37 |
38 | public bool Visible(MenuItem menuItem)
39 | {
40 | var user = UserController.Instance.GetCurrentUserInfo();
41 | return user != null && user.IsSuperUser;
42 | }
43 |
44 | public IDictionary GetSettings(MenuItem menuItem)
45 | {
46 | return PortalSettings.Current == null ? null : GetSettings(PortalSettings.Current.PortalId);
47 | }
48 |
49 | public IDictionary GetSettings(int portalId)
50 | {
51 | #if DEBUG
52 | var uiUrl = "http://localhost:8080/dist";
53 | #else
54 | var uiUrl = "./Modules/Dnn.AzureAD";
55 | #endif
56 | var apiUrl = "/DesktopModules/Admin/Dnn.PersonaBar/Modules/Dnn.AzureAD";
57 | var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
58 |
59 | return new Dictionary
60 | {
61 | {"uiUrl", uiUrl},
62 | {"apiUrl", apiUrl},
63 | {"libraryVersion", version },
64 | };
65 | }
66 |
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure.Extensibility/DotNetNuke.Authentication.Azure.Extensibility.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {42445032-9098-4160-930D-4127DC292695}
8 | Library
9 | Properties
10 | DotNetNuke.Authentication.Azure.Extensibility
11 | DotNetNuke.Authentication.Azure.Extensibility
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | bin\Release Legacy\
35 | TRACE
36 | true
37 | pdbonly
38 | AnyCPU
39 | 7.3
40 | prompt
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/roleMappings/roleMappingRow/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .collapsible-component-item {
3 | display: block;
4 | float: left;
5 | width: 100%;
6 | cursor: auto;
7 | &:not(:last-child) {
8 | border-bottom: 1px solid @alto;
9 | }
10 | div.collapsible-item {
11 | width: 100%;
12 | float: left;
13 | position: relative;
14 | padding: 15px 0 10px 0;
15 | box-sizing: border-box;
16 | cursor: auto;
17 | .row {
18 | float: left;
19 | width: 100%;
20 | .item-row-dnnrole {
21 | width: 50%;
22 | float: left;
23 | padding-left: 15px;
24 | word-break: break-all;
25 | }
26 | .item-row-aadrole {
27 | width: 35%;
28 | float: left;
29 | white-space: nowrap;
30 | overflow: hidden;
31 | text-overflow: ellipsis;
32 | }
33 | .item-row-primary {
34 | width: 10%;
35 | float: left;
36 | text-align: center;
37 | .checkMarkIcon {
38 | width: 16px;
39 | height: 16px;
40 | margin-left: auto;
41 | margin-right: auto;
42 | > svg {
43 | fill: @thunder;
44 | }
45 | }
46 | }
47 | .item-row-actionButtons {
48 | width: 8%;
49 | margin-right: 15px;
50 | float: right;
51 | &:not(:last-child) {
52 | float: left;
53 | margin-right: 0px;
54 | }
55 | .delete-icon, .edit-icon {
56 | margin-left: 5px;
57 | float: right;
58 | display: block;
59 | cursor: pointer;
60 | > svg {
61 | width: 16px;
62 | float: left;
63 | height: 16px;
64 | &:hover {
65 | fill: @thunder;
66 | }
67 | fill: @alto;
68 | }
69 | }
70 | .delete-icon-hidden {
71 | display: none;
72 | }
73 | .edit-icon-active {
74 | > svg {
75 | width: 16px;
76 | float: right;
77 | height: 16px;
78 | fill: @curiousBlue;
79 | }
80 | }
81 | }
82 | .item-row-wrapper {
83 | padding: 0 5px 0 5px;
84 | }
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/AzureUserData.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2019
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | #region Usings
25 |
26 | using System.Runtime.Serialization;
27 | using DotNetNuke.Entities.Users;
28 | using DotNetNuke.Services.Authentication.OAuth;
29 |
30 | #endregion
31 |
32 | namespace DotNetNuke.Authentication.Azure.Components
33 | {
34 | [DataContract]
35 | public class AzureUserData : UserData
36 | {
37 | #region Overrides
38 |
39 | public override string FirstName
40 | {
41 | get { return AzureFirstName; }
42 | set { }
43 | }
44 |
45 | public override string LastName
46 | {
47 | get { return AzureLastName; }
48 | set { }
49 | }
50 |
51 | public override string DisplayName
52 | {
53 | get { return AzureDisplayName; }
54 | set { }
55 | }
56 |
57 | #endregion
58 |
59 | [DataMember(Name = "given_name")]
60 | public string AzureFirstName { get; set; }
61 |
62 | [DataMember(Name = "family_name")]
63 | public string AzureLastName { get; set; }
64 |
65 | [DataMember(Name = "name")]
66 | public string AzureDisplayName { get; set; }
67 |
68 | public UserInfo ToUserInfo(bool usernamePrefixEnabled)
69 | {
70 | return new UserInfo()
71 | {
72 | DisplayName = this.DisplayName,
73 | FirstName = this.FirstName,
74 | LastName = this.LastName,
75 | Email = this.Email,
76 | Username = usernamePrefixEnabled ? $"Azure-{this.Id}" : this.Id
77 | };
78 | }
79 |
80 |
81 | }
82 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/userMappingRow/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .collapsible-component-item {
3 | display: block;
4 | float: left;
5 | width: 100%;
6 | cursor: auto;
7 | &:not(:last-child) {
8 | border-bottom: 1px solid @alto;
9 | }
10 | div.collapsible-item {
11 | width: 100%;
12 | float: left;
13 | position: relative;
14 | padding: 15px 0 10px 0;
15 | box-sizing: border-box;
16 | cursor: auto;
17 | .row {
18 | float: left;
19 | width: 100%;
20 | .item-row-dnnproperty {
21 | width: 50%;
22 | float: left;
23 | padding-left: 15px;
24 | word-break: break-all;
25 | }
26 | .item-row-aadproperty {
27 | width: 37%;
28 | float: left;
29 | white-space: nowrap;
30 | overflow: hidden;
31 | text-overflow: ellipsis;
32 | }
33 | .item-row-primary {
34 | width: 10%;
35 | float: left;
36 | text-align: center;
37 | .checkMarkIcon {
38 | width: 16px;
39 | height: 16px;
40 | margin-left: auto;
41 | margin-right: auto;
42 | > svg {
43 | fill: @thunder;
44 | }
45 | }
46 | }
47 | .item-row-actionButtons {
48 | width: 8%;
49 | margin-right: 15px;
50 | float: right;
51 | &:not(:last-child) {
52 | float: left;
53 | margin-right: 0px;
54 | }
55 | .delete-icon, .edit-icon {
56 | margin-left: 5px;
57 | float: right;
58 | display: block;
59 | cursor: pointer;
60 | > svg {
61 | width: 16px;
62 | float: left;
63 | height: 16px;
64 | &:hover {
65 | fill: @thunder;
66 | }
67 | fill: @alto;
68 | }
69 | }
70 | .delete-icon-hidden {
71 | display: none;
72 | }
73 | .edit-icon-active {
74 | > svg {
75 | width: 16px;
76 | float: right;
77 | height: 16px;
78 | fill: @curiousBlue;
79 | }
80 | }
81 | }
82 | .item-row-wrapper {
83 | padding: 0 5px 0 5px;
84 | }
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/roleMappings/roleMappingRow/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import { Collapsible, SvgIcons } from "@dnnsoftware/dnn-react-common";
4 | import "./style.less";
5 |
6 | class RoleMappingRow extends Component {
7 | /* eslint-disable react/no-did-mount-set-state */
8 | componentDidMount() {
9 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
10 | this.setState({
11 | opened
12 | });
13 | }
14 |
15 | toggle() {
16 | if ((this.props.openId !== "" && this.props.id === this.props.openId)) {
17 | this.props.Collapse();
18 | }
19 | else {
20 | this.props.OpenCollapse(this.props.id);
21 | }
22 | }
23 |
24 | /* eslint-disable react/no-danger */
25 | render() {
26 | const {props} = this;
27 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
28 | return (
29 |
30 |
31 |
32 |
33 | {props.dnnRoleName}
34 |
35 | {props.aadRoleName}
36 |
37 | {props.deletable &&
38 |
39 | }
40 | {props.editable &&
41 |
42 | }
43 |
44 |
45 |
46 |
{opened && props.children}
47 |
48 | );
49 | }
50 | }
51 |
52 | RoleMappingRow.propTypes = {
53 | mappingId: PropTypes.string,
54 | dnnRoleName: PropTypes.string,
55 | aadRoleName: PropTypes.string,
56 | deletable: PropTypes.bool,
57 | editable: PropTypes.bool,
58 | OpenCollapse: PropTypes.func,
59 | Collapse: PropTypes.func,
60 | onDelete: PropTypes.func,
61 | id: PropTypes.string,
62 | openId: PropTypes.string
63 | };
64 |
65 | RoleMappingRow.defaultProps = {
66 | collapsed: true,
67 | deletable: true,
68 | editable: true
69 | };
70 | export default (RoleMappingRow);
71 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/userMappingRow/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import { Collapsible, SvgIcons } from "@dnnsoftware/dnn-react-common";
4 | import "./style.less";
5 |
6 | class UserMappingRow extends Component {
7 | /* eslint-disable react/no-did-mount-set-state */
8 | componentDidMount() {
9 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
10 | this.setState({
11 | opened
12 | });
13 | }
14 |
15 | toggle() {
16 | if ((this.props.openId !== "" && this.props.id === this.props.openId)) {
17 | this.props.Collapse();
18 | }
19 | else {
20 | this.props.OpenCollapse(this.props.id);
21 | }
22 | }
23 |
24 | /* eslint-disable react/no-danger */
25 | render() {
26 | const {props} = this;
27 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
28 | return (
29 |
30 |
31 |
32 |
33 | {props.dnnPropertyName}
34 |
35 | {props.aadClaimName}
36 |
37 | {props.deletable &&
38 |
39 | }
40 | {props.editable &&
41 |
42 | }
43 |
44 |
45 |
46 |
{opened && props.children}
47 |
48 | );
49 | }
50 | }
51 |
52 | UserMappingRow.propTypes = {
53 | mappingId: PropTypes.string,
54 | dnnPropertyName: PropTypes.string,
55 | aadClaimName: PropTypes.string,
56 | deletable: PropTypes.bool,
57 | editable: PropTypes.bool,
58 | OpenCollapse: PropTypes.func,
59 | Collapse: PropTypes.func,
60 | onDelete: PropTypes.func,
61 | id: PropTypes.string,
62 | openId: PropTypes.string
63 | };
64 |
65 | UserMappingRow.defaultProps = {
66 | collapsed: true,
67 | deletable: false,
68 | editable: true
69 | };
70 | export default (UserMappingRow);
71 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/profileMappings/profileMappingRow/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index.less";
2 | .collapsible-component-profile {
3 | display: block;
4 | float: left;
5 | width: 100%;
6 | cursor: auto;
7 | &:not(:last-child) {
8 | border-bottom: 1px solid @alto;
9 | }
10 | div.collapsible-profile {
11 | width: 100%;
12 | float: left;
13 | position: relative;
14 | padding: 15px 0 10px 0;
15 | box-sizing: border-box;
16 | cursor: auto;
17 | .row {
18 | float: left;
19 | width: 100%;
20 | .item-row-dnnprofile {
21 | width: 35%;
22 | float: left;
23 | padding-left: 15px;
24 | word-break: break-all;
25 | }
26 | .item-row-aadprofile {
27 | width: 20%;
28 | float: left;
29 | }
30 | .item-row-aadextension {
31 | width: 30%;
32 | float: left;
33 | white-space: nowrap;
34 | overflow: hidden;
35 | text-overflow: ellipsis;
36 | }
37 | .item-row-primary {
38 | width: 10%;
39 | float: left;
40 | text-align: center;
41 | .checkMarkIcon {
42 | width: 16px;
43 | height: 16px;
44 | margin-left: auto;
45 | margin-right: auto;
46 | > svg {
47 | fill: @thunder;
48 | }
49 | }
50 | }
51 | .item-row-actionButtons {
52 | width: 8%;
53 | margin-right: 15px;
54 | float: right;
55 | &:not(:last-child) {
56 | float: left;
57 | margin-right: 0px;
58 | }
59 | .delete-icon, .edit-icon {
60 | margin-left: 5px;
61 | float: right;
62 | display: block;
63 | cursor: pointer;
64 | > svg {
65 | width: 16px;
66 | float: left;
67 | height: 16px;
68 | &:hover {
69 | fill: @thunder;
70 | }
71 | fill: @alto;
72 | }
73 | }
74 | .delete-icon-hidden {
75 | display: none;
76 | }
77 | .edit-icon-active {
78 | > svg {
79 | width: 16px;
80 | float: right;
81 | height: 16px;
82 | fill: @curiousBlue;
83 | }
84 | }
85 | }
86 | .item-row-wrapper {
87 | padding: 0 5px 0 5px;
88 | }
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/profileMappings/profileMappingRow/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import { Collapsible, SvgIcons } from "@dnnsoftware/dnn-react-common";
4 | import "./style.less";
5 |
6 | class ProfileMappingRow extends Component {
7 | /* eslint-disable react/no-did-mount-set-state */
8 | componentDidMount() {
9 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
10 | this.setState({
11 | opened
12 | });
13 | }
14 |
15 | toggle() {
16 | if ((this.props.openId !== "" && this.props.id === this.props.openId)) {
17 | this.props.Collapse();
18 | }
19 | else {
20 | this.props.OpenCollapse(this.props.id);
21 | }
22 | }
23 |
24 | /* eslint-disable react/no-danger */
25 | render() {
26 | const {props} = this;
27 | let opened = (this.props.openId !== "" && this.props.id === this.props.openId);
28 | return (
29 |
30 |
31 |
32 |
33 | {props.dnnProfilePropertyName}
34 |
35 | {props.aadClaimName}
36 |
37 | {props.deletable &&
38 |
39 | }
40 | {props.editable &&
41 |
42 | }
43 |
44 |
45 |
46 |
{opened && props.children}
47 |
48 | );
49 | }
50 | }
51 |
52 | ProfileMappingRow.propTypes = {
53 | profileMappingId: PropTypes.string,
54 | dnnProfilePropertyName: PropTypes.string,
55 | aadClaimName: PropTypes.string,
56 | deletable: PropTypes.bool,
57 | editable: PropTypes.bool,
58 | OpenCollapse: PropTypes.func,
59 | Collapse: PropTypes.func,
60 | onDelete: PropTypes.func,
61 | id: PropTypes.string,
62 | openId: PropTypes.string
63 | };
64 |
65 | ProfileMappingRow.defaultProps = {
66 | collapsed: true,
67 | deletable: true,
68 | editable: true
69 | };
70 | export default (ProfileMappingRow);
71 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/roleMappings/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index";
2 | .dnn-azuread-aad-roleMappingSettings {
3 | .items {
4 | margin: 30px 30px;
5 | width: 738px;
6 | float: left;
7 | box-sizing: border-box;
8 | .items-grid {
9 | border: solid 1px @alto;
10 | float: left;
11 | width: 100%;
12 | }
13 | .header-row {
14 | border-bottom: 1px solid @alto;
15 | padding: 10px 0 10px 0;
16 | width: 100%;
17 | float: left;
18 | overflow: hidden;
19 | }
20 | .header-DnnRole {
21 | width: 50%;
22 | float: left;
23 | font-weight: bolder;
24 | padding-left: 15px;
25 | }
26 | .header-AadRole {
27 | width: 20%;
28 | float: left;
29 | font-weight: bolder;
30 | }
31 | .collapsible-component {
32 | .collapsible-header {
33 | text-align: right;
34 | text-transform: none;
35 | padding-right: 40px;
36 | .collapse-icon {
37 | display: none;
38 | &.collapsed {
39 | display: none;
40 | }
41 | }
42 | }
43 | }
44 | .AddItemRow {
45 | text-align: right;
46 | width: 100%;
47 | float: right;
48 | margin: 0 0 15px 0;
49 | font-weight: bolder;
50 | border-bottom: 1px solid @alto;
51 | overflow: hidden;
52 | height: 25px;
53 | .sectionTitle {
54 | font-weight: bolder;
55 | float: left;
56 | }
57 | .AddItemBox {
58 | width: auto;
59 | float: right;
60 | color: @thunder;
61 | cursor: pointer;
62 | .add-icon {
63 | margin-left: 20px;
64 | margin-right: 5px;
65 | float: left;
66 | cursor: pointer;
67 | svg {
68 | width: 16px;
69 | float: left;
70 | height: 16px;
71 | fill: @thunder;
72 | }
73 | }
74 | }
75 | .AddItemBox-active {
76 | width: auto;
77 | float: right;
78 | color: @curiousBlue;
79 | .add-icon {
80 | margin-left: 20px;
81 | margin-right: 5px;
82 | float: left;
83 | svg {
84 | width: 16px;
85 | float: left;
86 | height: 16px;
87 | fill: @curiousBlue;
88 | }
89 | }
90 | }
91 | }
92 | .role-item {
93 | color: @thunder;
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index";
2 | .dnn-azuread-aad-userMappingSettings {
3 | .items {
4 | margin: 30px 30px;
5 | width: 738px;
6 | float: left;
7 | box-sizing: border-box;
8 | .items-grid {
9 | border: solid 1px @alto;
10 | float: left;
11 | width: 100%;
12 | }
13 | .header-row {
14 | border-bottom: 1px solid @alto;
15 | padding: 10px 0 10px 0;
16 | width: 100%;
17 | float: left;
18 | overflow: hidden;
19 | }
20 | .header-DnnProperty {
21 | width: 50%;
22 | float: left;
23 | font-weight: bolder;
24 | padding-left: 15px;
25 | }
26 | .header-AadProperty {
27 | width: 20%;
28 | float: left;
29 | font-weight: bolder;
30 | }
31 | .collapsible-component {
32 | .collapsible-header {
33 | text-align: right;
34 | text-transform: none;
35 | padding-right: 40px;
36 | .collapse-icon {
37 | display: none;
38 | &.collapsed {
39 | display: none;
40 | }
41 | }
42 | }
43 | }
44 | .AddItemRow {
45 | text-align: right;
46 | width: 100%;
47 | float: right;
48 | margin: 0 0 15px 0;
49 | font-weight: bolder;
50 | border-bottom: 1px solid @alto;
51 | overflow: hidden;
52 | height: 25px;
53 | .sectionTitle {
54 | font-weight: bolder;
55 | float: left;
56 | }
57 | .AddItemBox {
58 | width: auto;
59 | float: right;
60 | color: @thunder;
61 | cursor: pointer;
62 | .add-icon {
63 | margin-left: 20px;
64 | margin-right: 5px;
65 | float: left;
66 | cursor: pointer;
67 | svg {
68 | width: 16px;
69 | float: left;
70 | height: 16px;
71 | fill: @thunder;
72 | }
73 | }
74 | }
75 | .AddItemBox-active {
76 | width: auto;
77 | float: right;
78 | color: @curiousBlue;
79 | .add-icon {
80 | margin-left: 20px;
81 | margin-right: 5px;
82 | float: left;
83 | svg {
84 | width: 16px;
85 | float: left;
86 | height: 16px;
87 | fill: @curiousBlue;
88 | }
89 | }
90 | }
91 | }
92 | .role-item {
93 | color: @thunder;
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/profileMappings/style.less:
--------------------------------------------------------------------------------
1 | @import "~@dnnsoftware/dnn-react-common/styles/index";
2 | .dnn-azuread-aad-profileMappingSettings {
3 | .profile-items {
4 | margin: 30px 30px;
5 | width: 738px;
6 | float: left;
7 | box-sizing: border-box;
8 | .profile-items-grid {
9 | border: solid 1px @alto;
10 | float: left;
11 | width: 100%;
12 | }
13 | .header-row {
14 | border-bottom: 1px solid @alto;
15 | padding: 10px 0 10px 0;
16 | width: 100%;
17 | float: left;
18 | overflow: hidden;
19 | }
20 | .header-DnnProfileProperty {
21 | width: 35%;
22 | float: left;
23 | font-weight: bolder;
24 | padding-left: 15px;
25 | }
26 | .header-AadClaim {
27 | width: 40%;
28 | float: left;
29 | font-weight: bolder;
30 | }
31 | .collapsible-component {
32 | .collapsible-header {
33 | text-align: right;
34 | text-transform: none;
35 | padding-right: 40px;
36 | .collapse-icon {
37 | display: none;
38 | &.collapsed {
39 | display: none;
40 | }
41 | }
42 | }
43 | }
44 | .AddItemRow {
45 | text-align: right;
46 | width: 100%;
47 | float: right;
48 | margin: 0 0 15px 0;
49 | font-weight: bolder;
50 | border-bottom: 1px solid @alto;
51 | overflow: hidden;
52 | height: 25px;
53 | .sectionTitle {
54 | font-weight: bolder;
55 | float: left;
56 | }
57 | .AddItemBox {
58 | width: auto;
59 | float: right;
60 | color: @thunder;
61 | cursor: pointer;
62 | .add-icon {
63 | margin-left: 20px;
64 | margin-right: 5px;
65 | float: left;
66 | cursor: pointer;
67 | svg {
68 | width: 16px;
69 | float: left;
70 | height: 16px;
71 | fill: @thunder;
72 | }
73 | }
74 | }
75 | .AddItemBox-active {
76 | width: auto;
77 | float: right;
78 | color: @curiousBlue;
79 | .add-icon {
80 | margin-left: 20px;
81 | margin-right: 5px;
82 | float: left;
83 | svg {
84 | width: 16px;
85 | float: left;
86 | height: 16px;
87 | fill: @curiousBlue;
88 | }
89 | }
90 | }
91 | }
92 | .profile-item {
93 | color: @thunder;
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/services/applicationService.js:
--------------------------------------------------------------------------------
1 | import util from "../utils";
2 | class ApplicationService {
3 | getServiceFramework(controller) {
4 | let sf = util.utilities.sf;
5 | sf.controller = controller;
6 | return sf;
7 | }
8 |
9 | getSettings(callback) {
10 | const sf = this.getServiceFramework("AzureAD");
11 | sf.get("GetSettings", {}, callback);
12 | }
13 |
14 | updateGeneralSettings(payload, callback, failureCallback) {
15 | const sf = this.getServiceFramework("AzureAD");
16 | sf.post("UpdateGeneralSettings", payload, callback, failureCallback);
17 | }
18 |
19 | updateAdvancedSyncSettings(payload, callback, failureCallback) {
20 | const sf = this.getServiceFramework("AzureAD");
21 | sf.post("UpdateAdvancedSyncSettings", payload, callback, failureCallback);
22 | }
23 |
24 | updateAdvancedMoreSettings(payload, callback, failureCallback) {
25 | const sf = this.getServiceFramework("AzureAD");
26 | sf.post("UpdateAdvancedMoreSettings", payload, callback, failureCallback);
27 | }
28 |
29 | updateProfileMapping(payload, callback, failureCallback) {
30 | const sf = this.getServiceFramework("AzureAD");
31 | sf.post("UpdateProfileMapping", payload, callback, failureCallback);
32 | }
33 |
34 | deleteProfileMapping(payload, callback, failureCallback) {
35 | const sf = this.getServiceFramework("AzureAD");
36 | sf.post("DeleteProfileMapping", payload, callback, failureCallback);
37 | }
38 | getProfileSettings(callback) {
39 | const sf = this.getServiceFramework("AzureAD");
40 | sf.get("GetProfileSettings", {}, callback);
41 | }
42 |
43 | getProfileProperties(callback) {
44 | const sf = this.getServiceFramework("AzureAD");
45 | sf.get("GetProfileProperties", {}, callback);
46 | }
47 |
48 | getRoleMappingSettings(callback) {
49 | const sf = this.getServiceFramework("AzureAD");
50 | sf.get("GetRoleMappingSettings", {}, callback);
51 | }
52 |
53 | getAvailableRoles(callback) {
54 | const sf = this.getServiceFramework("AzureAD");
55 | sf.get("GetAvailableRoles", {}, callback);
56 | }
57 |
58 | updateRoleMapping(payload, callback, failureCallback) {
59 | const sf = this.getServiceFramework("AzureAD");
60 | sf.post("UpdateRoleMapping", payload, callback, failureCallback);
61 | }
62 |
63 | deleteRoleMapping(payload, callback, failureCallback) {
64 | const sf = this.getServiceFramework("AzureAD");
65 | sf.post("DeleteRoleMapping", payload, callback, failureCallback);
66 | }
67 |
68 | getUserMappingSettings(callback) {
69 | const sf = this.getServiceFramework("AzureAD");
70 | sf.get("GetUserMappingSettings", {}, callback);
71 | }
72 |
73 | updateUserMapping(payload, callback, failureCallback) {
74 | const sf = this.getServiceFramework("AzureAD");
75 | sf.post("UpdateUserMapping", payload, callback, failureCallback);
76 | }
77 |
78 | }
79 | const applicationService = new ApplicationService();
80 | export default applicationService;
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from "react";
2 | import PropTypes from "prop-types";
3 | import { connect } from "react-redux";
4 | import {PersonaBarPage, PersonaBarPageHeader, PersonaBarPageBody, DnnTabs as Tabs} from "@dnnsoftware/dnn-react-common";
5 | import SettingsActions from "../actions/settings";
6 | import GeneralSettings from "./general";
7 | import SyncSettings from "./advanced/sync";
8 | import MoreSettings from "./advanced/more";
9 | import ProfileMappings from "./profileMappings";
10 | import UserMappings from "./userMappings";
11 | import RoleMappings from "./roleMappings";
12 | import resx from "../resources";
13 |
14 | import "./style.less";
15 |
16 | class App extends Component {
17 |
18 | constructor() {
19 | super();
20 |
21 | }
22 | onSelectTab(index) {
23 | this.props.dispatch(SettingsActions.switchTab(index));
24 | }
25 | onSelectSubTab(index) {
26 | this.props.dispatch(SettingsActions.switchMappingSubTab(index));
27 | }
28 | render() {
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
39 |
40 |
46 |
47 |
48 |
49 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | );
65 | }
66 | }
67 |
68 | App.propTypes = {
69 | dispatch: PropTypes.func.isRequired,
70 | selectedTab: PropTypes.number,
71 | selectedMappingSubTab: PropTypes.number
72 | };
73 |
74 |
75 | function mapStateToProps(state) {
76 | return {
77 | selectedTab: state.settings.selectedTab,
78 | selectedMappingSubTab: state.settings.selectedMappingSubTab
79 | };
80 | }
81 |
82 | export default connect(mapStateToProps)(App);
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Data/UserMappingsRepository.cs:
--------------------------------------------------------------------------------
1 | using DotNetNuke.Authentication.Azure.Components.Models;
2 | using DotNetNuke.Common;
3 | using DotNetNuke.Data;
4 | using DotNetNuke.Entities.Users;
5 | using DotNetNuke.Framework;
6 | using System;
7 | using System.Linq;
8 |
9 | namespace DotNetNuke.Authentication.Azure.Data
10 | {
11 | public class UserMappingsRepository : ServiceLocator, IUserMappingsRepository
12 | {
13 | protected override Func GetFactory()
14 | {
15 | return () => new UserMappingsRepository();
16 | }
17 |
18 | public IQueryable GetUserMappings(int portalId)
19 | {
20 | IQueryable result = null;
21 |
22 | using (IDataContext ctx = DataContext.Instance())
23 | {
24 | var rep = ctx.GetRepository();
25 | result = rep.Find("WHERE PortalId = @0", portalId).AsQueryable();
26 | }
27 |
28 | return result;
29 | }
30 |
31 | public UserMapping GetUserMapping(string dnnPropertyName, int portalId)
32 | {
33 | Requires.NotNullOrEmpty("DnnPropertyName", dnnPropertyName);
34 |
35 | UserMapping result;
36 | using (IDataContext ctx = DataContext.Instance())
37 | {
38 | var rep = ctx.GetRepository();
39 | result = rep.Find("WHERE DnnPropertyName = @0 AND PortalId = @1", dnnPropertyName, portalId).FirstOrDefault();
40 | }
41 | return result;
42 | }
43 |
44 | public void UpdateUserMapping(string dnnPropertyName, string aadClaimName, int portalId)
45 | {
46 | Requires.NotNullOrEmpty("DnnPropertyName", dnnPropertyName);
47 |
48 | var userMapping = GetUserMapping(dnnPropertyName, portalId);
49 | if (userMapping == null)
50 | {
51 | throw new ArgumentException($"User mapping '{dnnPropertyName}' not found in portal {portalId}");
52 | }
53 |
54 | userMapping.AadClaimName = aadClaimName;
55 | userMapping.PortalId = portalId;
56 | userMapping.LastModifiedOnDate = DateTime.UtcNow;
57 | userMapping.LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID;
58 | using (IDataContext ctx = DataContext.Instance())
59 | {
60 | var rep = ctx.GetRepository();
61 | rep.Update(userMapping);
62 | }
63 | }
64 |
65 | public void InsertUserMapping(string dnnPropertyName, string aadClaimName, int portalId)
66 | {
67 | Requires.NotNullOrEmpty("DnnPropertyName", dnnPropertyName);
68 | Requires.NotNullOrEmpty("AadClaimName", aadClaimName);
69 |
70 | var userMapping = new UserMapping
71 | {
72 | DnnPropertyName = dnnPropertyName,
73 | CreatedByUserId = UserController.Instance.GetCurrentUserInfo().UserID,
74 | CreatedOnDate = DateTime.UtcNow,
75 | AadClaimName = aadClaimName,
76 | PortalId = portalId,
77 | LastModifiedOnDate = DateTime.UtcNow,
78 | LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID
79 | };
80 | using (IDataContext ctx = DataContext.Instance())
81 | {
82 | var rep = ctx.GetRepository();
83 | rep.Insert(userMapping);
84 | }
85 |
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Auth/AadAuthMessageHandler.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2020
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | #region Usings
25 | using DotNetNuke.Authentication.Azure.Components;
26 | using DotNetNuke.Instrumentation;
27 | using DotNetNuke.Web.Api.Auth;
28 | using System;
29 | using System.Net.Http;
30 | using System.Security.Principal;
31 | using System.Threading;
32 | #endregion
33 |
34 | namespace DotNetNuke.Authentication.Azure.Auth
35 | {
36 | ///
37 | /// This class implements Azure AD authentication using JWT scheme
38 | ///
39 | public class AadAuthMessageHandler : AuthMessageHandlerBase
40 | {
41 | #region constants, properties, etc.
42 | private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(AadAuthMessageHandler));
43 | private readonly IAadController _b2cController = AadController.Instance;
44 | public override string AuthScheme => _b2cController.SchemeType;
45 | public override bool BypassAntiForgeryToken => true;
46 | internal static bool IsEnabled { get; set; }
47 | #endregion
48 |
49 | #region constructor
50 | public AadAuthMessageHandler(bool includeByDefault, bool forceSsl)
51 | : base(includeByDefault, forceSsl)
52 | {
53 | // Once an instance is enabled and gets registered in
54 | // ServicesRoutingManager.RegisterAuthenticationHandlers()
55 | // this scheme gets marked as enabled.
56 | IsEnabled = true;
57 | }
58 |
59 | #endregion
60 |
61 | #region implementation
62 |
63 | public override HttpResponseMessage OnInboundRequest(HttpRequestMessage request, CancellationToken cancellationToken)
64 | {
65 | if (NeedsAuthentication(request))
66 | {
67 | TryToAuthenticate(request);
68 | }
69 | return base.OnInboundRequest(request, cancellationToken);
70 | }
71 |
72 | private void TryToAuthenticate(HttpRequestMessage request)
73 | {
74 | try
75 | {
76 | var username = _b2cController.ValidateToken(request);
77 | if (!string.IsNullOrEmpty(username))
78 | {
79 | if (Logger.IsDebugEnabled) Logger.Debug($"Authenticated user '{username}'");
80 | SetCurrentPrincipal(new GenericPrincipal(new GenericIdentity(username, AuthScheme), null), request);
81 | }
82 | }
83 | catch (Exception ex)
84 | {
85 | Logger.Error("Unexpected error in authenticating the user. " + ex);
86 | }
87 | }
88 |
89 | #endregion
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 | *.csproj.user
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | [Pp]roduction/
16 | [Qq][Aa]/
17 |
18 | x64/
19 | build/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 |
24 | # Roslyn cache directories
25 | *.ide/
26 |
27 | # MSTest test Results
28 | [Tt]est[Rr]esult*/
29 | [Bb]uild[Ll]og.*
30 |
31 | #NUNIT
32 | *.VisualState.xml
33 | TestResult.xml
34 |
35 | # Build Results of an ATL Project
36 | [Dd]ebugPS/
37 | [Rr]eleasePS/
38 | dlldata.c
39 |
40 | *_i.c
41 | *_p.c
42 | *_i.h
43 | *.ilk
44 | *.meta
45 | *.obj
46 | *.pch
47 | *.pdb
48 | *.pgc
49 | *.pgd
50 | *.rsp
51 | *.sbr
52 | *.tlb
53 | *.tli
54 | *.tlh
55 | *.tmp
56 | *.tmp_proj
57 | *.log
58 | *.vspscc
59 | *.vssscc
60 | .builds
61 | *.pidb
62 | *.svclog
63 | *.scc
64 |
65 | # Chutzpah Test files
66 | _Chutzpah*
67 |
68 | # Visual C++ cache files
69 | ipch/
70 | *.aps
71 | *.ncb
72 | *.opensdf
73 | *.sdf
74 | *.cachefile
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 | *.vspx
80 |
81 | # TFS 2012 Local Workspace
82 | $tf/
83 |
84 | # Guidance Automation Toolkit
85 | *.gpState
86 |
87 | # ReSharper is a .NET coding add-in
88 | _ReSharper*/
89 | *.[Rr]e[Ss]harper
90 | *.DotSettings.user
91 |
92 | # JustCode is a .NET coding addin-in
93 | .JustCode
94 |
95 | # TeamCity is a build add-in
96 | _TeamCity*
97 |
98 | # DotCover is a Code Coverage Tool
99 | *.dotCover
100 |
101 | # NCrunch
102 | _NCrunch_*
103 | .*crunch*.local.xml
104 |
105 | # MightyMoose
106 | *.mm.*
107 | AutoTest.Net/
108 |
109 | # Web workbench (sass)
110 | .sass-cache/
111 |
112 | # Installshield output folder
113 | [Ee]xpress/
114 |
115 | # DocProject is a documentation generator add-in
116 | DocProject/buildhelp/
117 | DocProject/Help/*.HxT
118 | DocProject/Help/*.HxC
119 | DocProject/Help/*.hhc
120 | DocProject/Help/*.hhk
121 | DocProject/Help/*.hhp
122 | DocProject/Help/Html2
123 | DocProject/Help/html
124 |
125 | # Click-Once directory
126 | publish/
127 |
128 | # Publish Web Output
129 | *.[Pp]ublish.xml
130 | *.azurePubxml
131 | ## TODO: Comment the next line if you want to checkin your
132 | ## web deploy settings but do note that will include unencrypted
133 | ## passwords
134 | *.pubxml
135 |
136 | # NuGet Packages Directory
137 | packages/*
138 | ## TODO: If the tool you use requires repositories.config
139 | ## uncomment the next line
140 | #!packages/repositories.config
141 |
142 | # Enable "build/" folder in the NuGet Packages folder since
143 | # NuGet packages use it for MSBuild targets.
144 | # This line needs to be after the ignore of the build folder
145 | # (and the packages folder if the line above has been uncommented)
146 | !packages/build/
147 |
148 | # Windows Azure Build Output
149 | csx/
150 | *.build.csdef
151 |
152 | # Windows Store app package directory
153 | AppPackages/
154 |
155 | # Others
156 | sql/
157 | *.Cache
158 | ClientBin/
159 | [Ss]tyle[Cc]op.*
160 | ~$*
161 | *~
162 | *.dbmdl
163 | *.dbproj.schemaview
164 | *.pfx
165 | *.publishsettings
166 | node_modules/
167 |
168 | # RIA/Silverlight projects
169 | Generated_Code/
170 |
171 | # Backup & report files from converting an old project file
172 | # to a newer Visual Studio version. Backup files are not needed,
173 | # because we have git ;-)
174 | _UpgradeReport_Files/
175 | Backup*/
176 | UpgradeLog*.XML
177 | UpgradeLog*.htm
178 |
179 | # SQL Server files
180 | *.mdf
181 | *.ldf
182 |
183 | # Business Intelligence projects
184 | *.rdl.data
185 | *.bim.layout
186 | *.bim_*.settings
187 |
188 | # Microsoft Fakes
189 | FakesAssemblies/
190 |
191 | ############
192 | ## Windows
193 | ############
194 |
195 | # Windows image file caches
196 | [Tt]humbs.db
197 |
198 | # Folder config file
199 | [Dd]esktop.ini
200 |
201 | .vs/
202 | /DotNetNuke.Authentication.Azure/packages
203 | /Releases
204 | /DotNetNuke.Authentication.Azure/AzureAD.Web/package-lock.json
205 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require("webpack");
2 | const packageJson = require("./package.json");
3 | const path = require("path");
4 | const isProduction = process.env.NODE_ENV === "production";
5 | const languages = {
6 | "en": null
7 | // TODO: create locallizaton files per language
8 | // "de": require("./localizations/de.json"),
9 | // "es": require("./localizations/es.json"),
10 | // "fr": require("./localizations/fr.json"),
11 | // "it": require("./localizations/it.json"),
12 | // "nl": require("./localizations/nl.json")
13 | };
14 |
15 | const webpackExternals = require("@dnnsoftware/dnn-react-common/WebpackExternals");
16 |
17 | module.exports = (env, argv) => {
18 | const isProduction = argv.mode === "production";
19 | return {
20 | entry: "./src/main.jsx",
21 | optimization: {
22 | minimize: isProduction
23 | },
24 | output: {
25 | path: path.resolve(__dirname, "../admin/personaBar/scripts/bundles/"),
26 | filename: "bundle-en.js",
27 | publicPath: isProduction ? "" : "http://localhost:8080/dist/scripts/bundles"
28 | },
29 | devServer: {
30 | allowedHosts: "all"
31 | },
32 | resolve: {
33 | extensions: ["*", ".js", ".json", ".jsx"],
34 | modules: [
35 | path.resolve('./src'), // Look in src first
36 | path.resolve('./node_modules') // Try local node_modules
37 | ]
38 | },
39 |
40 | module: {
41 | rules: [
42 | {
43 | test: /\.(js|jsx)$/,
44 | exclude: /node_modules/,
45 | enforce: "pre",
46 | loader: "eslint-loader",
47 | options: {
48 | fix: true,
49 | },
50 | },
51 | {
52 | test: /\.less$/,
53 | use: [{
54 | loader: 'style-loader' // creates style nodes from JS strings
55 | }, {
56 | loader: 'css-loader', // translates CSS into CommonJS
57 | options: { modules: "global" }
58 | }, {
59 | loader: 'less-loader' // compiles Less to CSS
60 | }]
61 | },
62 | {
63 | test: /\.(js|jsx)$/,
64 | exclude: /node_modules/,
65 | use: {
66 | loader: 'babel-loader',
67 | options: {
68 | presets: ['@babel/preset-env','@babel/preset-react']
69 | }
70 | }
71 | },
72 | {
73 | test: /\.(ttf|woff)$/,
74 | use: {
75 | loader: 'url-loader?limit=8192'
76 | }
77 | },
78 | {
79 | test: /\.(gif|png)$/,
80 | loader: "url-loader?mimetype=image/png"
81 | }
82 | ]
83 | },
84 | externals: webpackExternals,
85 |
86 | plugins: isProduction
87 | ? [
88 | new webpack.DefinePlugin({
89 | VERSION: JSON.stringify(packageJson.version),
90 | "process.env": {
91 | NODE_ENV: JSON.stringify("production")
92 | }
93 | })
94 | ]
95 | : [
96 | new webpack.DefinePlugin({
97 | VERSION: JSON.stringify(packageJson.version),
98 | "process.env": {
99 | NODE_ENV: JSON.stringify("development")
100 | }
101 | })
102 | ],
103 | };
104 | };
105 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Data/RoleMappingsRepository.cs:
--------------------------------------------------------------------------------
1 | using DotNetNuke.Authentication.Azure.Components.Models;
2 | using DotNetNuke.Common;
3 | using DotNetNuke.Data;
4 | using DotNetNuke.Entities.Users;
5 | using DotNetNuke.Framework;
6 | using System;
7 | using System.Linq;
8 |
9 | namespace DotNetNuke.Authentication.Azure.Data
10 | {
11 | public class RoleMappingsRepository : ServiceLocator, IRoleMappingsRepository
12 | {
13 | protected override Func GetFactory()
14 | {
15 | return () => new RoleMappingsRepository();
16 | }
17 |
18 | public IQueryable GetRoleMappings(int portalId)
19 | {
20 | IQueryable result = null;
21 |
22 | using (IDataContext ctx = DataContext.Instance())
23 | {
24 | var rep = ctx.GetRepository();
25 | result = rep.Find("WHERE PortalId = @0", portalId).AsQueryable();
26 | }
27 |
28 | return result;
29 | }
30 |
31 | public RoleMapping GetRoleMapping(string dnnRoleName, int portalId)
32 | {
33 | Requires.NotNullOrEmpty("DnnRoleName", dnnRoleName);
34 |
35 | RoleMapping result;
36 | using (IDataContext ctx = DataContext.Instance())
37 | {
38 | var rep = ctx.GetRepository();
39 | result = rep.Find("WHERE DnnRoleName = @0 AND PortalId = @1", dnnRoleName, portalId).FirstOrDefault();
40 | }
41 | return result;
42 | }
43 |
44 | public void UpdateRoleMapping(string originalDnnRoleName, string dnnRoleName, string aadRoleName, int portalId)
45 | {
46 | Requires.NotNullOrEmpty("OriginalDnnRoleName", originalDnnRoleName);
47 | Requires.NotNullOrEmpty("DnnRoleName", dnnRoleName);
48 | Requires.NotNullOrEmpty("AadRoleName", aadRoleName);
49 |
50 | var roleMapping = GetRoleMapping(originalDnnRoleName, portalId);
51 | if (roleMapping == null)
52 | {
53 | throw new ArgumentException($"Role mapping '{originalDnnRoleName}' not found in portal {portalId}");
54 | }
55 |
56 | roleMapping.DnnRoleName = dnnRoleName;
57 | roleMapping.AadRoleName = aadRoleName;
58 | roleMapping.PortalId = portalId;
59 | roleMapping.LastModifiedOnDate = DateTime.UtcNow;
60 | roleMapping.LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID;
61 | using (IDataContext ctx = DataContext.Instance())
62 | {
63 | var rep = ctx.GetRepository();
64 | rep.Update(roleMapping);
65 | }
66 | }
67 |
68 | public void InsertRoleMapping(string dnnRoleName, string aadRoleName, int portalId)
69 | {
70 | Requires.NotNullOrEmpty("DnnRoleName", dnnRoleName);
71 | Requires.NotNullOrEmpty("AadRoleName", aadRoleName);
72 |
73 | var roleMapping = new RoleMapping
74 | {
75 | DnnRoleName = dnnRoleName,
76 | CreatedByUserId = UserController.Instance.GetCurrentUserInfo().UserID,
77 | CreatedOnDate = DateTime.UtcNow,
78 | AadRoleName = aadRoleName,
79 | PortalId = portalId,
80 | LastModifiedOnDate = DateTime.UtcNow,
81 | LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID
82 | };
83 | using (IDataContext ctx = DataContext.Instance())
84 | {
85 | var rep = ctx.GetRepository();
86 | rep.Insert(roleMapping);
87 | }
88 | }
89 |
90 | public void DeleteRoleMapping(string dnnRoleName, int portalId)
91 | {
92 | Requires.NotNullOrEmpty("DnnRoleName", dnnRoleName);
93 |
94 | var roleMapping = GetRoleMapping(dnnRoleName, portalId);
95 | if (roleMapping != null)
96 | {
97 | using (IDataContext ctx = DataContext.Instance())
98 | {
99 | var rep = ctx.GetRepository();
100 | rep.Delete(roleMapping);
101 | }
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Data/ProfileMappingsRepository.cs:
--------------------------------------------------------------------------------
1 | using DotNetNuke.Authentication.Azure.Components.Models;
2 | using DotNetNuke.Common;
3 | using DotNetNuke.Data;
4 | using DotNetNuke.Entities.Users;
5 | using DotNetNuke.Framework;
6 | using System;
7 | using System.Linq;
8 |
9 | namespace DotNetNuke.Authentication.Azure.Data
10 | {
11 | public class ProfileMappingsRepository : ServiceLocator, IProfileMappingsRepository
12 | {
13 | protected override Func GetFactory()
14 | {
15 | return () => new ProfileMappingsRepository();
16 | }
17 |
18 | public IQueryable GetProfileMappings(int portalId)
19 | {
20 | IQueryable result = null;
21 |
22 | using (IDataContext ctx = DataContext.Instance())
23 | {
24 | var rep = ctx.GetRepository();
25 | result = rep.Find("WHERE PortalId = @0", portalId).AsQueryable();
26 | }
27 |
28 | return result;
29 | }
30 |
31 | public ProfileMapping GetProfileMapping(string dnnProfilePropertyName, int portalId)
32 | {
33 | Requires.NotNullOrEmpty("DnnProfilePropertyName", dnnProfilePropertyName);
34 |
35 | ProfileMapping result;
36 | using (IDataContext ctx = DataContext.Instance())
37 | {
38 | var rep = ctx.GetRepository();
39 | result = rep.Find("WHERE DnnProfilePropertyName = @0 AND PortalId = @1", dnnProfilePropertyName, portalId).FirstOrDefault();
40 | }
41 | return result;
42 | }
43 |
44 | public void UpdateProfileMapping(string dnnProfilePropertyName, string aadClaimName, int portalId)
45 | {
46 | Requires.NotNullOrEmpty("DnnProfilePropertyName", dnnProfilePropertyName);
47 | Requires.NotNullOrEmpty("AadClaimName", aadClaimName);
48 |
49 | var profileMapping = GetProfileMapping(dnnProfilePropertyName, portalId);
50 | if (profileMapping == null)
51 | {
52 | throw new ArgumentException($"Profile mapping '{dnnProfilePropertyName}' not found in portal {portalId}");
53 | }
54 |
55 | profileMapping.AadClaimName = aadClaimName;
56 | profileMapping.PortalId = portalId;
57 | profileMapping.LastModifiedOnDate = DateTime.UtcNow;
58 | profileMapping.LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID;
59 | using (IDataContext ctx = DataContext.Instance())
60 | {
61 | var rep = ctx.GetRepository();
62 | rep.Update(profileMapping);
63 | }
64 | }
65 |
66 | public void InsertProfileMapping(string dnnProfilePropertyName, string aadClaimName, int portalId)
67 | {
68 | Requires.NotNullOrEmpty("DnnProfilePropertyName", dnnProfilePropertyName);
69 | Requires.NotNullOrEmpty("AadClaimName", aadClaimName);
70 |
71 | var profileMapping = new ProfileMapping
72 | {
73 | DnnProfilePropertyName = dnnProfilePropertyName,
74 | CreatedByUserId = UserController.Instance.GetCurrentUserInfo().UserID,
75 | CreatedOnDate = DateTime.UtcNow,
76 | AadClaimName = aadClaimName,
77 | PortalId = portalId,
78 | LastModifiedOnDate = DateTime.UtcNow,
79 | LastModifiedByUserId = UserController.Instance.GetCurrentUserInfo().UserID
80 | };
81 | using (IDataContext ctx = DataContext.Instance())
82 | {
83 | var rep = ctx.GetRepository();
84 | rep.Insert(profileMapping);
85 | }
86 | }
87 |
88 | public void DeleteProfileMapping(string dnnProfilePropertyName, int portalId)
89 | {
90 | Requires.NotNullOrEmpty("DnnProfilePropertyname", dnnProfilePropertyName);
91 |
92 | var profileMapping = GetProfileMapping(dnnProfilePropertyName, portalId);
93 | if (profileMapping != null)
94 | {
95 | using (IDataContext ctx = DataContext.Instance())
96 | {
97 | var rep = ctx.GetRepository();
98 | rep.Delete(profileMapping);
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Login.ascx.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2010-2017
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | #region Usings
25 |
26 | using System;
27 | using System.Collections.Specialized;
28 | using System.Diagnostics;
29 | using System.Web;
30 | using DotNetNuke.Authentication.Azure.Components;
31 | using DotNetNuke.Services.Authentication;
32 | using DotNetNuke.Services.Authentication.OAuth;
33 | using DotNetNuke.Services.Exceptions;
34 | using DotNetNuke.Services.Localization;
35 | using DotNetNuke.UI.Skins.Controls;
36 | using log4net;
37 |
38 | #endregion
39 |
40 | namespace DotNetNuke.Authentication.Azure
41 | {
42 | public partial class Login : OAuthLoginBase
43 | {
44 | private ILog _logger = LogManager.GetLogger(typeof(Login));
45 | private AzureConfig config;
46 | protected override string AuthSystemApplicationName => AzureConfig.ServiceName;
47 |
48 | public override bool SupportsRegistration => true;
49 |
50 | protected override void AddCustomProperties(NameValueCollection properties)
51 | {
52 | ((AzureClient)OAuthClient).AddCustomProperties(properties);
53 | }
54 |
55 | protected override UserData GetCurrentUser()
56 | {
57 | return OAuthClient.GetCurrentUser();
58 | }
59 |
60 | protected override void OnInit(EventArgs e)
61 | {
62 | base.OnInit(e);
63 |
64 |
65 | loginButton.Click += loginButton_Click;
66 | registerButton.Click += loginButton_Click;
67 |
68 | OAuthClient = new AzureClient(PortalId, Mode);
69 |
70 | loginItem.Visible = (Mode == AuthMode.Login);
71 | registerItem.Visible = (Mode == AuthMode.Register);
72 |
73 | config = new AzureConfig(AzureConfig.ServiceName, PortalId);
74 | var hasVerificationCode = ((AzureClient)OAuthClient).IsCurrentService() && OAuthClient.HaveVerificationCode();
75 | if ((config.AutoRedirect && Request["legacy"] != "1") || hasVerificationCode || !string.IsNullOrEmpty(Request["error"]))
76 | loginButton_Click(null, null);
77 | }
78 |
79 | private void loginButton_Click(object sender, EventArgs e)
80 | {
81 | if (!string.IsNullOrEmpty(Request["error"]))
82 | {
83 | var errorMessage = Localization.GetString("LoginError", LocalResourceFile);
84 | errorMessage = string.Format(errorMessage, Request["error"], Request["error_description"]);
85 | _logger.Error(errorMessage);
86 | if (string.IsNullOrEmpty(config.OnErrorUri))
87 | {
88 | UI.Skins.Skin.AddModuleMessage(this, errorMessage, ModuleMessage.ModuleMessageType.RedError);
89 | }
90 | else
91 | {
92 | Response.Redirect($"{config.OnErrorUri}?error={Request["error"]}&error_description={HttpContext.Current.Server.UrlEncode(Request["error_description"])}");
93 | }
94 | }
95 | else
96 | {
97 | AuthorisationResult result = OAuthClient.Authorize();
98 | if (result == AuthorisationResult.Denied)
99 | {
100 | if (string.IsNullOrEmpty(config.OnErrorUri))
101 | {
102 | UI.Skins.Skin.AddModuleMessage(this, Localization.GetString("PrivateConfirmationMessage", Localization.SharedResourceFile), ModuleMessage.ModuleMessageType.YellowWarning);
103 | }
104 | else
105 | {
106 | Response.Redirect($"{config.OnErrorUri}?error=Denied&error_description={HttpContext.Current.Server.UrlEncode(Localization.GetString("PrivateConfirmationMessage", Localization.SharedResourceFile))}");
107 | }
108 | }
109 | else
110 | {
111 | if (!string.IsNullOrEmpty(((AzureClient)OAuthClient).RedirectUrl)) {
112 | RedirectURL = ((AzureClient)OAuthClient).RedirectUrl;
113 | }
114 | }
115 | }
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Providers/DataProviders/SqlDataProvider/04.00.00.SqlDataProvider:
--------------------------------------------------------------------------------
1 | IF NOT EXISTS (SELECT * FROM {databaseOwner}[{objectQualifier}Schedule] WHERE TypeFullName = 'DotNetNuke.Authentication.Azure.ScheduledTasks.SyncSchedule, DotNetNuke.Authentication.Azure')
2 | BEGIN
3 | INSERT INTO {databaseOwner}[{objectQualifier}Schedule]
4 | ([TypeFullName]
5 | ,[TimeLapse]
6 | ,[TimeLapseMeasurement]
7 | ,[RetryTimeLapse]
8 | ,[RetryTimeLapseMeasurement]
9 | ,[RetainHistoryNum]
10 | ,[AttachToEvent]
11 | ,[CatchUpEnabled]
12 | ,[Enabled]
13 | ,[ObjectDependencies]
14 | ,[Servers]
15 | ,[CreatedByUserID]
16 | ,[CreatedOnDate]
17 | ,[LastModifiedByUserID]
18 | ,[LastModifiedOnDate]
19 | ,[FriendlyName])
20 | VALUES
21 | ('DotNetNuke.Authentication.Azure.ScheduledTasks.SyncSchedule, DotNetNuke.Authentication.Azure',
22 | 3, 'h',
23 | 30, 'm',
24 | 10,
25 | '', 'false', 'true',
26 | '', NULL,
27 | NULL, NULL,
28 | NULL, NULL,
29 | 'Azure AD Sync')
30 | END
31 |
32 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_UserMappings]', N'U') IS NULL
33 | BEGIN
34 | CREATE TABLE {databaseOwner}[{objectQualifier}AzureAD_UserMappings](
35 | [UserMappingId] [int] NOT NULL IDENTITY (1, 1),
36 | [DnnPropertyName] [nvarchar](50) NOT NULL,
37 | [AadClaimName] [nvarchar](100) NULL,
38 | [PortalId] [int] NULL,
39 | [CreatedByUserId] [int] NULL,
40 | [CreatedOnDate] [datetime] NULL,
41 | [LastModifiedByUserId] [int] NULL,
42 | [LastModifiedOnDate] [datetime] NULL,
43 | CONSTRAINT [PK_AzureAD_UserMappings] PRIMARY KEY CLUSTERED
44 | (
45 | [UserMappingId] ASC
46 | ) ON [PRIMARY]
47 | ) ON [PRIMARY]
48 |
49 | -- Insert default values:
50 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
51 | SELECT 'PortalId', '', PortalId, -1, GETDATE(), -1, GETDATE()
52 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
53 |
54 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
55 | SELECT 'Id', 'upn', PortalID, -1, GETDATE(), -1, GETDATE()
56 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
57 |
58 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
59 | SELECT 'FirstName', 'given_name', PortalId, -1, GETDATE(), -1, GETDATE()
60 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
61 |
62 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
63 | SELECT 'LastName', 'family_name', PortalId, -1, GETDATE(), -1, GETDATE()
64 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
65 |
66 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
67 | SELECT 'DisplayName', 'name', PortalId, -1, GETDATE(), -1, GETDATE()
68 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
69 |
70 | INSERT INTO {databaseOwner}[{objectQualifier}AzureAD_UserMappings] ([DnnPropertyName],[AadClaimName],[PortalId],[CreatedByUserId],[CreatedOnDate],[LastModifiedByUserId],[LastModifiedOnDate])
71 | SELECT 'Email', 'upn', PortalId, -1, GETDATE(), -1, GETDATE()
72 | FROM (Select PortalId FROM {databaseOwner}[{objectQualifier}Portals] UNION SELECT PortalId = -1) p
73 | END
74 | GO
75 |
76 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_ProfileMappings]', N'U') IS NULL
77 | BEGIN
78 | CREATE TABLE {databaseOwner}[{objectQualifier}AzureAD_ProfileMappings](
79 | [ProfileMappingId] [int] NOT NULL IDENTITY (1, 1),
80 | [DnnProfilePropertyName] [nvarchar](50) NOT NULL,
81 | [AadClaimName] [nvarchar](100) NULL,
82 | [PortalId] [int] NULL,
83 | [CreatedByUserId] [int] NULL,
84 | [CreatedOnDate] [datetime] NULL,
85 | [LastModifiedByUserId] [int] NULL,
86 | [LastModifiedOnDate] [datetime] NULL,
87 | CONSTRAINT [PK_AzureAD_ProfileMappings] PRIMARY KEY CLUSTERED
88 | (
89 | [ProfileMappingId] ASC
90 | ) ON [PRIMARY]
91 | ) ON [PRIMARY]
92 |
93 | END
94 | GO
95 |
96 | IF OBJECT_ID(N'{databaseOwner}[{objectQualifier}AzureAD_RoleMappings]', N'U') IS NULL
97 | BEGIN
98 | CREATE TABLE {databaseOwner}[{objectQualifier}AzureAD_RoleMappings](
99 | [RoleMappingId] [int] NOT NULL IDENTITY (1, 1),
100 | [DnnRoleName] [nvarchar](50) NOT NULL,
101 | [AadRoleName] [nvarchar](100) NULL,
102 | [PortalId] [int] NULL,
103 | [CreatedByUserId] [int] NULL,
104 | [CreatedOnDate] [datetime] NULL,
105 | [LastModifiedByUserId] [int] NULL,
106 | [LastModifiedOnDate] [datetime] NULL,
107 | CONSTRAINT [PK_AzureAD_RoleMappings] PRIMARY KEY CLUSTERED
108 | (
109 | [RoleMappingId] ASC
110 | ) ON [PRIMARY]
111 | ) ON [PRIMARY]
112 |
113 | END
114 | GO
115 |
116 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/reducers/settingsReducer.js:
--------------------------------------------------------------------------------
1 | import { settings as ActionTypes } from "../constants/actionTypes";
2 |
3 | export default function settings(state = {
4 | selectedTab: 0
5 | }, action) {
6 | switch (action.type) {
7 | case ActionTypes.RETRIEVED_SETTINGS:
8 | return { ...state,
9 | enabled: action.data.enabled,
10 | useGlobalSettings: action.data.useGlobalSettings,
11 | autoRedirect: action.data.autoRedirect,
12 | autoAuthorize: action.data.autoAuthorize,
13 | autoMatchExistingUsers: action.data.autoMatchExistingUsers,
14 | apiKey: action.data.apiKey,
15 | apiSecret: action.data.apiSecret,
16 | redirectUri: action.data.redirectUri,
17 | onErrorUri: action.data.onErrorUri,
18 | tenantId: action.data.tenantId,
19 | aadTenantId: action.data.aadTenantId,
20 | aadAppClientId: action.data.aadAppClientId,
21 | aadAppSecret: action.data.aadAppSecret,
22 | graphUseCustomParams: action.data.graphUseCustomParams,
23 | jwtAudiences: action.data.jwtAudiences,
24 | roleSyncEnabled: action.data.roleSyncEnabled,
25 | userSyncEnabled: action.data.userSyncEnabled,
26 | profileSyncEnabled: action.data.profileSyncEnabled,
27 | apiResource: action.data.apiResource,
28 | scopes: action.data.scopes,
29 | clientModified: action.data.clientModified,
30 | usernamePrefixEnabled: action.data.usernamePrefixEnabled,
31 | groupNamePrefixEnabled: action.data.groupNamePrefixEnabled,
32 | authorizationCodePrompt: action.data.authorizationCodePrompt,
33 | domainHint: action.data.domainHint
34 | };
35 | case ActionTypes.SETTINGS_CLIENT_MODIFIED:
36 | return { ...state,
37 | enabled: action.data.enabled,
38 | useGlobalSettings: action.data.useGlobalSettings,
39 | autoRedirect: action.data.autoRedirect,
40 | autoAuthorize: action.data.autoAuthorize,
41 | autoMatchExistingUsers: action.data.autoMatchExistingUsers,
42 | apiKey: action.data.apiKey,
43 | apiSecret: action.data.apiSecret,
44 | redirectUri: action.data.redirectUri,
45 | onErrorUri: action.data.onErrorUri,
46 | tenantId: action.data.tenantId,
47 | aadTenantId: action.data.aadTenantId,
48 | aadAppClientId: action.data.aadAppClientId,
49 | aadAppSecret: action.data.aadAppSecret,
50 | graphUseCustomParams: action.data.graphUseCustomParams,
51 | jwtAudiences: action.data.jwtAudiences,
52 | roleSyncEnabled: action.data.roleSyncEnabled,
53 | userSyncEnabled: action.data.userSyncEnabled,
54 | profileSyncEnabled: action.data.profileSyncEnabled,
55 | apiResource: action.data.apiResource,
56 | scopes: action.data.scopes,
57 | clientModified: action.data.clientModified,
58 | usernamePrefixEnabled: action.data.usernamePrefixEnabled,
59 | groupNamePrefixEnabled: action.data.groupNamePrefixEnabled,
60 | authorizationCodePrompt: action.data.authorizationCodePrompt,
61 | domainHint: action.data.domainHint
62 | };
63 | case ActionTypes.UPDATED_SETTINGS:
64 | return { ...state,
65 | clientModified: action.data.clientModified
66 | };
67 | case ActionTypes.RETRIEVED_PROFILESETTINGS:
68 | return { ...state,
69 | profileMapping: action.data.profileMapping
70 | };
71 | case ActionTypes.RETRIEVED_ROLEMAPPINGSETTINGS:
72 | return { ...state,
73 | roleMapping: action.data.roleMapping
74 | };
75 | case ActionTypes.RETRIEVED_AVAILABLEROLES:
76 | return { ...state,
77 | roles: action.data.roles
78 | };
79 | case ActionTypes.SWITCH_TAB:
80 | return {
81 | ...state,
82 | selectedTab: action.payload
83 | };
84 | case ActionTypes.SWITCH_MAPPING_SUBTAB:
85 | return {
86 | ...state,
87 | selectedSubTab: action.payload
88 | };
89 | case ActionTypes.CANCELLED_PROFILEMAPPING_CLIENT_MODIFIED:
90 | return { ...state,
91 | profileMappingClientModified: action.data.profileMappingClientModified
92 | };
93 | case ActionTypes.PROFILEMAPPINGS_CLIENT_MODIFIED:
94 | return { ...state,
95 | profileMappingDetail: action.data.profileMappingDetail,
96 | profileMappingClientModified: action.data.profileMappingClientModified
97 | };
98 | case ActionTypes.RETRIEVED_PROFILEPROPERTIES:
99 | return { ...state,
100 | profileProperties: action.data.profileProperties
101 | };
102 | case ActionTypes.ROLEMAPPINGS_CLIENT_MODIFIED:
103 | return { ...state,
104 | roleProperties: action.data.roleProperties
105 | };
106 | case ActionTypes.RETRIEVED_USERMAPPINGSETTINGS:
107 | return { ...state,
108 | userMapping: action.data.userMapping
109 | };
110 | case ActionTypes.USERMAPPINGS_CLIENT_MODIFIED:
111 | return { ...state,
112 | userMappingDetail: action.data.userMappingDetail,
113 | userMappingClientModified: action.data.userMappingClientModified
114 | };
115 | default:
116 | return { ...state
117 | };
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/App_LocalResources/Settings.ascx.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Microosft Entra ID Settings
122 |
123 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/App_LocalResources/Login.ascx.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Sign in with Microsoft Entra ID
122 |
123 |
124 | Error: {0}<br/>Details: {1}
125 |
126 |
127 | Register with Microsoft Entra ID
128 |
129 |
130 | Microsoft Entra ID
131 |
132 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/index.jsx:
--------------------------------------------------------------------------------
1 | import React, {Component} from "react";
2 | import PropTypes from "prop-types";
3 | import { connect } from "react-redux";
4 | import SettingsActions from "../../actions/settings";
5 | import UserMappingRow from "./userMappingRow";
6 | import UserMappingEditor from "./userMappingEditor";
7 | import "./style.less";
8 | import utils from "../../utils";
9 | import resx from "../../resources";
10 |
11 | class UserMappings extends Component {
12 |
13 | constructor() {
14 | super();
15 |
16 | this.state = {
17 | openId: "",
18 | tableFields: [],
19 | error: {
20 | mapping: false
21 | }
22 | };
23 | }
24 | UNSAFE_componentWillMount() {
25 | const {props} = this;
26 |
27 | props.dispatch(SettingsActions.getUserMappingSettings());
28 | }
29 |
30 | UNSAFE_componentWillReceiveProps(nextProps) {
31 | const {state} = this;
32 |
33 | state.error["mapping"] = (nextProps.mapping === null);
34 | }
35 |
36 | onUpdateMapping(mappingDetail) {
37 | const {props} = this;
38 |
39 | let payload = {
40 | DnnPropertyName: mappingDetail.DnnPropertyName,
41 | AadClaimName: mappingDetail.AadClaimName
42 | };
43 | props.dispatch(SettingsActions.updateUserMapping(payload, () => {
44 | utils.utilities.notify(resx.get("MappingUpdateSuccess"));
45 | this.collapse();
46 | props.dispatch(SettingsActions.getUserMappingSettings());
47 | }, (error) => {
48 | const errorMessage = JSON.parse(error.responseText);
49 | utils.utilities.notifyError(errorMessage.Message);
50 | }));
51 | }
52 |
53 | onDeleteMapping(mappingId) {
54 | const {props} = this;
55 | utils.utilities.confirm(resx.get("MappingDeletedWarning"), resx.get("Yes"), resx.get("No"), () => {
56 | let originalUserMappingName = mappingId.split("-")[0];
57 |
58 | let payload = {
59 | dnnMappingName: originalUserMappingName
60 | };
61 | props.dispatch(SettingsActions.deleteUserMapping(payload, () => {
62 | utils.utilities.notify(resx.get("MappingDeleteSuccess"));
63 | this.collapse();
64 | props.dispatch(SettingsActions.getUserMappingSettings());
65 | }, (error) => {
66 | const errorMessage = JSON.parse(error.responseText);
67 | utils.utilities.notifyError(errorMessage.Message);
68 | }));
69 | });
70 | }
71 |
72 | onClickCancel() {
73 | utils.utilities.closePersonaBar();
74 | }
75 |
76 | /* eslint-disable react/no-did-update-set-state */
77 | componentDidUpdate(prevProps) {
78 | const {props} = this;
79 | if (props !== prevProps) {
80 | let tableFields = [];
81 | if (tableFields.length === 0) {
82 | tableFields.push({ "name": resx.get("DnnProperty.Header"), "id": "DnnProperty" });
83 | tableFields.push({ "name": resx.get("AadProperty.Header"), "id": "AadProperty" });
84 | }
85 | this.setState({tableFields});
86 | }
87 | }
88 |
89 | uncollapse(id) {
90 | this.setState({
91 | openId: id
92 | });
93 | }
94 |
95 | collapse() {
96 | if (this.state.openId !== "") {
97 | this.setState({
98 | openId: ""
99 | });
100 | }
101 | }
102 |
103 | toggle(openId) {
104 | if (openId !== "") {
105 | this.uncollapse(openId);
106 | }
107 | }
108 |
109 | renderHeader() {
110 | let tableHeaders = this.state.tableFields.map((field) => {
111 | let className = "header-" + field.id;
112 | return
113 | {field.name}
114 |
;
115 | });
116 | return {tableHeaders}
;
117 | }
118 |
119 | renderMappings() {
120 | let i = 0;
121 | if (this.props.mapping) {
122 | return this.props.mapping.map((item, index) => {
123 | let id = "row-" + i++;
124 | let mappingId = item.DnnPropertyName + "-" + item.AadClaimName;
125 | return (
126 |
138 |
146 |
147 | );
148 | });
149 | }
150 | }
151 |
152 | /* eslint-disable react/no-danger */
153 | render() {
154 | return (
155 |
156 |
157 |
158 |
{resx.get("lblUsersMapping")}
159 |
160 |
161 | {this.renderHeader()}
162 | {this.renderMappings()}
163 |
164 |
165 |
166 | );
167 | }
168 | }
169 |
170 | UserMappings.propTypes = {
171 | mapping: PropTypes.array
172 | };
173 |
174 |
175 | function mapStateToProps(state) {
176 | return {
177 | mapping: state.settings.userMapping
178 | };
179 | }
180 |
181 | export default connect(mapStateToProps)(UserMappings);
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Components/Graph/GraphExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graph;
2 | using Microsoft.Identity.Client;
3 | using System.IO;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace DotNetNuke.Authentication.Azure.Components.Graph
8 | {
9 | // Added Sync extensions methods because the current Graph nuget package is
10 | // getting frozen on async calls. Horrible workaround but can't get it working.
11 | // See https://stackoverflow.com/questions/55105321/microsoft-graph-getasync-hangs-indefinitely
12 | // See https://stackoverflow.com/questions/66109869/getting-an-access-token-for-the-graph-api-works-in-a-console-app-but-just-hangs
13 | internal static class GraphExtensions
14 | {
15 | internal static IUserMemberOfCollectionWithReferencesPage GetSync(this IUserMemberOfCollectionWithReferencesRequest request)
16 | {
17 | using (var task = Task.Run(async () => await request.GetAsync()))
18 | {
19 | while (!task.IsCompleted)
20 | Thread.Sleep(10);
21 | return task.Result;
22 | }
23 | }
24 | internal static User GetSync(this IUserRequest request)
25 | {
26 | using (var task = Task.Run(async () => await request.GetAsync()))
27 | {
28 | while (!task.IsCompleted)
29 | Thread.Sleep(10);
30 | return task.Result;
31 | }
32 | }
33 |
34 | internal static ProfilePhoto GetSync(this IProfilePhotoRequest request)
35 | {
36 | using (var task = Task.Run(async () => await request.GetAsync()))
37 | {
38 | while (!task.IsCompleted)
39 | Thread.Sleep(10);
40 | return task.Result;
41 | }
42 | }
43 |
44 | internal static Stream GetSync(this IProfilePhotoContentRequest request)
45 | {
46 | using (var task = Task.Run(async () => await request.GetAsync()))
47 | {
48 | while (!task.IsCompleted)
49 | Thread.Sleep(10);
50 | return task.Result;
51 | }
52 | }
53 |
54 |
55 |
56 | internal static void DeleteSync(this IUserRequest request)
57 | {
58 | using (var task = Task.Run(async () => await request.DeleteAsync()))
59 | {
60 | while (!task.IsCompleted)
61 | Thread.Sleep(10);
62 | return;
63 | }
64 | }
65 |
66 | internal static IGraphServiceUsersCollectionPage GetSync(this IGraphServiceUsersCollectionRequest request)
67 | {
68 | using (var task = Task.Run(async () => await request.GetAsync()))
69 | {
70 | while (!task.IsCompleted)
71 | Thread.Sleep(10);
72 | return task.Result;
73 | }
74 | }
75 |
76 | internal static User AddSync(this IGraphServiceUsersCollectionRequest request, User user)
77 | {
78 | using (var task = Task.Run(async () => await request.AddAsync(user)))
79 | {
80 | while (!task.IsCompleted)
81 | Thread.Sleep(10);
82 | return task.Result;
83 | }
84 | }
85 |
86 | internal static User UpdateSync(this IUserRequest request, User user)
87 | {
88 | using (var task = Task.Run(async () => await request.UpdateAsync(user)))
89 | {
90 | while (!task.IsCompleted)
91 | Thread.Sleep(10);
92 | return task.Result;
93 | }
94 | }
95 |
96 | internal static IGraphServiceGroupsCollectionPage GetSync(this IGraphServiceGroupsCollectionRequest request)
97 | {
98 | using (var task = Task.Run(async () => await request.GetAsync()))
99 | {
100 | while (!task.IsCompleted)
101 | Thread.Sleep(10);
102 | return task.Result;
103 | }
104 | }
105 |
106 | internal static IGroupTransitiveMembersCollectionWithReferencesPage GetSync(this IGroupTransitiveMembersCollectionWithReferencesRequest request)
107 | {
108 | using (var task = Task.Run(async () => await request.GetAsync()))
109 | {
110 | while (!task.IsCompleted)
111 | Thread.Sleep(10);
112 | return task.Result;
113 | }
114 | }
115 |
116 |
117 | internal static Group AddSync(this IGraphServiceGroupsCollectionRequest request, Group group)
118 | {
119 | using (var task = Task.Run(async () => await request.AddAsync(group)))
120 | {
121 | while (!task.IsCompleted)
122 | Thread.Sleep(10);
123 | return task.Result;
124 | }
125 | }
126 |
127 |
128 |
129 | internal static Group UpdateSync(this IGroupRequest request, Group group)
130 | {
131 | using (var task = Task.Run(async () => await request.UpdateAsync(group)))
132 | {
133 | while (!task.IsCompleted)
134 | Thread.Sleep(10);
135 | return task.Result;
136 | }
137 | }
138 |
139 |
140 | internal static void AddSync(this IGroupMembersCollectionReferencesRequest request, User user)
141 | {
142 | using (var task = Task.Run(async () => await request.AddAsync(user)))
143 | {
144 | while (!task.IsCompleted)
145 | Thread.Sleep(10);
146 | return;
147 | }
148 | }
149 |
150 | internal static void DeleteSync(this IDirectoryObjectReferenceRequest request)
151 | {
152 | using (var task = Task.Run(async () => await request.DeleteAsync()))
153 | {
154 | while (!task.IsCompleted)
155 | Thread.Sleep(10);
156 | return;
157 | }
158 | }
159 |
160 |
161 | internal static AuthenticationResult ExecuteSync(this AcquireTokenForClientParameterBuilder request)
162 | {
163 | using (var task = Task.Run(async () => await request.ExecuteAsync()))
164 | {
165 | while (!task.IsCompleted)
166 | Thread.Sleep(10);
167 | return task.Result;
168 | }
169 | }
170 |
171 | internal static T RunSynchronous(this Task t)
172 | {
173 | using (var task = Task.Run(async () => await t))
174 | {
175 | while (!task.IsCompleted)
176 | Thread.Sleep(10);
177 | return task.Result;
178 | }
179 | }
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/userMappings/userMappingEditor/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import { connect } from "react-redux";
4 | import "./style.less";
5 | import { SingleLineInputWithError, GridSystem, Button, InputGroup } from "@dnnsoftware/dnn-react-common";
6 | import SettingsActions from "../../../actions/settings";
7 | import util from "../../../utils";
8 | import resx from "../../../resources";
9 |
10 | class UserMappingEditor extends Component {
11 | constructor() {
12 | super();
13 |
14 | this.state = {
15 | mappingDetail: {
16 | DnnPropertyName: "",
17 | AadClaimName: ""
18 | },
19 | error: {
20 | dnnPropertyName: false,
21 | aadClaimName: false
22 | },
23 | triedToSubmit: false
24 | };
25 | }
26 |
27 | componentWillMount() {
28 | const {props} = this;
29 | const {state} = this;
30 |
31 | state.mappingDetail["MappingId"] = props.mappingId;
32 | state.mappingDetail["DnnPropertyName"] = props.dnnPropertyName;
33 | state.mappingDetail["AadClaimName"] = props.aadClaimName;
34 |
35 | state.error["dnnPropertyName"] = (props.dnnPropertyName === null);
36 | state.error["aadClaimName"] = (props.aadClaimName === null);
37 | }
38 |
39 | /* eslint-disable react/no-did-update-set-state */
40 | componentDidUpdate(prevProps) {
41 | const {props, state} = this;
42 | if ((props !== prevProps) && props.mappingDetail ) {
43 | if (props.mappingDetail["DnnPropertyName"] === undefined || props.mappingDetail["DnnPropertyName"] === "") {
44 | state.error["dnnPropertyName"] = true;
45 | }
46 | else if (props.mappingDetail["DnnPropertyName"] !== "" && props.mappingDetail["DnnPropertyName"] !== undefined) {
47 | state.error["dnnPropertyName"] = false;
48 | }
49 |
50 | this.setState({
51 | mappingDetail: Object.assign({}, props.mappingDetail),
52 | triedToSubmit: false,
53 | error: state.error
54 | });
55 | }
56 | }
57 |
58 | onSettingChange(key, event) {
59 | let {state, props} = this;
60 | let mappingDetail = Object.assign({}, state.mappingDetail);
61 |
62 | if (key === "DnnPropertyName") {
63 | state.error["dnnPropertyName"] = !props.onValidate(mappingDetail, event.value);
64 | }
65 |
66 | if (mappingDetail[key] === "" && key === "AadClaimName" && props.dnnPropertyName !== "PortalId") {
67 | state.error["aadClaimName"] = true;
68 | }
69 | else if (mappingDetail[key] !== "" && key === "AadClaimName") {
70 | state.error["aadClaimName"] = false;
71 | }
72 |
73 | mappingDetail[key] = typeof (event) === "object" ? event.target.value : event;
74 |
75 | this.setState({
76 | mappingDetail: mappingDetail,
77 | triedToSubmit: false,
78 | error: state.error
79 | });
80 |
81 | props.dispatch(SettingsActions.userMappingClientModified(mappingDetail));
82 | }
83 |
84 | onSave() {
85 | const {props, state} = this;
86 | this.setState({
87 | triedToSubmit: true
88 | });
89 | if (state.error.dnnPropertyName || state.error.aadClaimName) {
90 | return;
91 | }
92 |
93 | props.onUpdate(state.mappingDetail);
94 | props.Collapse();
95 | }
96 |
97 | onCancel() {
98 | const {props} = this;
99 |
100 | if (props.mappingClientModified) {
101 | util.utilities.confirm(resx.get("SettingsRestoreWarning"), resx.get("Yes"), resx.get("No"), () => {
102 | props.dispatch(SettingsActions.cancelUserMappingClientModified());
103 | props.Collapse();
104 | });
105 | }
106 | else {
107 | props.Collapse();
108 | }
109 | }
110 |
111 | /* eslint-disable react/no-danger */
112 | render() {
113 | if (this.state.mappingDetail !== undefined || this.props.id === "add") {
114 | const columnOne =
115 |
116 |
124 |
125 |
;
126 | const columnTwo =
127 |
128 |
138 |
139 |
;
140 |
141 | return (
142 |
143 |
{[columnOne, columnTwo]}
144 |
145 |
148 | {resx.get("Cancel")}
149 |
150 |
153 | {resx.get("SaveSettings")}
154 |
155 |
156 |
157 | );
158 | }
159 | else return
;
160 | }
161 | }
162 |
163 | UserMappingEditor.propTypes = {
164 | dispatch: PropTypes.func.isRequired,
165 | mappingDetail: PropTypes.object,
166 | mappingId: PropTypes.string,
167 | dnnPropertyName: PropTypes.string,
168 | aadClaimName: PropTypes.string,
169 | Collapse: PropTypes.func,
170 | onUpdate: PropTypes.func,
171 | id: PropTypes.string,
172 | mappingClientModified: PropTypes.bool,
173 | onValidate: PropTypes.func
174 | };
175 |
176 | function mapStateToProps() {
177 | return {
178 | };
179 | }
180 |
181 | export default connect(mapStateToProps)(UserMappingEditor);
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/AzureAD.Web/src/components/roleMappings/roleMappingEditor/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import PropTypes from "prop-types";
3 | import { connect } from "react-redux";
4 | import "./style.less";
5 | import { SingleLineInputWithError, GridSystem, Button, InputGroup, DropdownWithError } from "@dnnsoftware/dnn-react-common";
6 | import SettingsActions from "../../../actions/settings";
7 | import util from "../../../utils";
8 | import resx from "../../../resources";
9 |
10 | class RoleMappingEditor extends Component {
11 | constructor() {
12 | super();
13 |
14 | this.state = {
15 | mappingDetail: {
16 | DnnRoleName: "",
17 | AadRoleName: ""
18 | },
19 | error: {
20 | dnnRoleName: false,
21 | aadRoleName: false
22 | },
23 | triedToSubmit: false
24 | };
25 | }
26 |
27 | componentWillMount() {
28 | const {props} = this;
29 | const {state} = this;
30 |
31 | state.mappingDetail["MappingId"] = props.mappingId;
32 | state.mappingDetail["DnnRoleName"] = props.dnnRoleName;
33 | state.mappingDetail["AadRoleName"] = props.aadRoleName;
34 |
35 | state.error["dnnRoleName"] = (props.dnnRoleName === null);
36 | state.error["aadRoleName"] = (props.aadRoleName === null);
37 | }
38 |
39 | /* eslint-disable react/no-did-update-set-state */
40 | componentDidUpdate(prevProps) {
41 | const {props, state} = this;
42 | if ((props !== prevProps) && props.mappingDetail ) {
43 | if (props.mappingDetail["DnnRoleName"] === undefined || props.mappingDetail["DnnRoleName"] === "") {
44 | state.error["dnnRoleName"] = true;
45 | }
46 | else if (props.mappingDetail["DnnRoleName"] !== "" && props.mappingDetail["DnnRoleName"] !== undefined) {
47 | state.error["dnnRoleName"] = false;
48 | }
49 |
50 | this.setState({
51 | mappingDetail: Object.assign({}, props.mappingDetail),
52 | triedToSubmit: false,
53 | error: state.error
54 | });
55 | }
56 | }
57 |
58 | onSettingChange(key, event) {
59 | let {state, props} = this;
60 | let mappingDetail = Object.assign({}, state.mappingDetail);
61 |
62 | if (key === "DnnRoleName") {
63 | state.error["dnnRoleName"] = !props.onValidate(mappingDetail, event.value);
64 | }
65 |
66 | if (mappingDetail[key] === "" && key === "AadRoleName") {
67 | state.error["aadRoleName"] = true;
68 | }
69 | else if (mappingDetail[key] !== "" && key === "AadRoleName") {
70 | state.error["aadRoleName"] = false;
71 | }
72 |
73 | if (key === "DnnRoleName") {
74 | mappingDetail[key] = event.value;
75 | }
76 | else {
77 | mappingDetail[key] = typeof (event) === "object" ? event.target.value : event;
78 | }
79 |
80 | this.setState({
81 | mappingDetail: mappingDetail,
82 | triedToSubmit: false,
83 | error: state.error
84 | });
85 |
86 | props.dispatch(SettingsActions.roleMappingClientModified(mappingDetail));
87 | }
88 |
89 | getRolePropertyOptions() {
90 | let options = [];
91 |
92 | if (this.props.availableRoles !== undefined) {
93 | options = this.props.availableRoles.map((item) => {
94 | return { label: item, value: item };
95 | });
96 | }
97 | return options;
98 | }
99 |
100 | onSave() {
101 | const {props, state} = this;
102 | this.setState({
103 | triedToSubmit: true
104 | });
105 | if (state.error.dnnRoleName || state.error.aadRoleName) {
106 | return;
107 | }
108 |
109 | props.onUpdate(state.mappingDetail);
110 | props.Collapse();
111 | }
112 |
113 | onCancel() {
114 | const {props} = this;
115 |
116 | if (props.mappingClientModified) {
117 | util.utilities.confirm(resx.get("SettingsRestoreWarning"), resx.get("Yes"), resx.get("No"), () => {
118 | props.dispatch(SettingsActions.cancelRoleMappingClientModified());
119 | props.Collapse();
120 | });
121 | }
122 | else {
123 | props.Collapse();
124 | }
125 | }
126 |
127 | /* eslint-disable react/no-danger */
128 | render() {
129 | if (this.state.mappingDetail !== undefined || this.props.id === "add") {
130 | const columnOne =
131 |
132 |
143 |
144 |
;
145 | const columnTwo =
146 |
147 |
157 |
158 |
;
159 |
160 | return (
161 |
162 |
{[columnOne, columnTwo]}
163 |
164 |
167 | {resx.get("Cancel")}
168 |
169 |
172 | {resx.get("SaveSettings")}
173 |
174 |
175 |
176 | );
177 | }
178 | else return
;
179 | }
180 | }
181 |
182 | RoleMappingEditor.propTypes = {
183 | dispatch: PropTypes.func.isRequired,
184 | mappingDetail: PropTypes.object,
185 | mappingId: PropTypes.string,
186 | dnnRoleName: PropTypes.string,
187 | aadRoleName: PropTypes.string,
188 | Collapse: PropTypes.func,
189 | onUpdate: PropTypes.func,
190 | id: PropTypes.string,
191 | mappingClientModified: PropTypes.bool,
192 | availableRoles: PropTypes.array,
193 | onValidate: PropTypes.func
194 | };
195 |
196 | function mapStateToProps() {
197 | return {
198 | // profileMappingDetail: state.siteBehavior.aliasDetail,
199 | // profileMappingClientModified: state.siteBehavior.siteAliasClientModified
200 | };
201 | }
202 |
203 | export default connect(mapStateToProps)(RoleMappingEditor);
--------------------------------------------------------------------------------
/DotNetNuke.Authentication.Azure/Services/AzureADProviderSettings.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 |
3 | //
4 | // Intelequia Software solutions - https://intelequia.com
5 | // Copyright (c) 2010-2017
6 | // by Intelequia Software Solutions
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
10 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
11 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions
14 | // of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | // DEALINGS IN THE SOFTWARE.
21 |
22 | #endregion
23 |
24 | using System.Runtime.Serialization;
25 | using DotNetNuke.Authentication.Azure.Components;
26 |
27 | namespace DotNetNuke.Authentication.Azure.Services
28 | {
29 | [DataContract]
30 | public class AzureADProviderSettings
31 | {
32 | [DataMember(Name = "tenantId")]
33 | public string TenantId { get; set; }
34 | [DataMember(Name = "apiKey")]
35 | public string ApiKey { get; set; }
36 | [DataMember(Name = "apiSecret")]
37 | public string ApiSecret { get; set; }
38 | [DataMember(Name = "redirectUri")]
39 | public string RedirectUri { get; set; }
40 | [DataMember(Name = "onErrorUri")]
41 | public string OnErrorUri { get; set; }
42 | [DataMember(Name = "autoRedirect")]
43 | public bool AutoRedirect { get; set; }
44 | [DataMember(Name = "enabled")]
45 | public bool Enabled { get; set; }
46 | [DataMember(Name = "useGlobalSettings")]
47 | public bool UseGlobalSettings { get; set; }
48 | [DataMember(Name = "aadTenantId")]
49 | public string AadTenantId { get; set; }
50 | [DataMember(Name = "aadAppClientId")]
51 | public string AadAppClientId { get; set; }
52 | [DataMember(Name = "aadAppSecret")]
53 | public string AadAppSecret { get; set; }
54 | [DataMember(Name = "graphUseCustomParams")]
55 | public bool GraphUseCustomParams { get; set; }
56 | [DataMember(Name = "jwtAudiences")]
57 | public string JwtAudiences { get; set; }
58 | [DataMember(Name = "roleSyncEnabled")]
59 | public bool RoleSyncEnabled { get; set; }
60 | [DataMember(Name = "userSyncEnabled")]
61 | public bool UserSyncEnabled { get; set; }
62 | [DataMember(Name = "profileSyncEnabled")]
63 | public bool ProfileSyncEnabled { get; set; }
64 | [DataMember(Name = "apiResource")]
65 | public string ApiResource { get; set; }
66 | [DataMember(Name = "scopes")]
67 | public string Scopes { get; set; }
68 | [DataMember(Name = "usernamePrefixEnabled")]
69 | public bool UsernamePrefixEnabled { get; set; }
70 | [DataMember(Name = "groupNamePrefixEnabled")]
71 | public bool GroupNamePrefixEnabled { get; set; }
72 | [DataMember(Name = "autoAuthorize")]
73 | public bool AutoAuthorize { get; set; }
74 | [DataMember(Name = "authorizationCodePrompt")]
75 | public string AuthorizationCodePrompt { set; get; }
76 | [DataMember(Name = "domainHint")]
77 | public string DomainHint { get; set; }
78 | [DataMember(Name = "autoMatchExistingUsers")]
79 | public bool AutoMatchExistingUsers { get; set; }
80 |
81 |
82 |
83 | public static AzureADProviderSettings LoadSettings(string service, int portalId)
84 | {
85 | var config = new AzureConfig(service, portalId);
86 | return new AzureADProviderSettings
87 | {
88 | TenantId = config.TenantId,
89 | ApiKey = config.APIKey,
90 | ApiSecret = config.APISecret,
91 | RedirectUri = config.RedirectUri,
92 | OnErrorUri = config.OnErrorUri,
93 | AutoRedirect = config.AutoRedirect,
94 | AutoAuthorize = config.AutoAuthorize,
95 | AutoMatchExistingUsers = config.AutoMatchExistingUsers,
96 | AadTenantId = config.AADTenantId,
97 | AadAppClientId = config.AADApplicationId,
98 | AadAppSecret = config.AADApplicationKey,
99 | GraphUseCustomParams = config.GraphUseCustomParams,
100 | Enabled = config.Enabled,
101 | UseGlobalSettings = config.UseGlobalSettings,
102 | JwtAudiences = config.JwtAudiences,
103 | RoleSyncEnabled = config.RoleSyncEnabled,
104 | UserSyncEnabled = config.UserSyncEnabled,
105 | ProfileSyncEnabled = config.ProfileSyncEnabled,
106 | ApiResource = config.APIResource,
107 | Scopes = config.Scopes,
108 | UsernamePrefixEnabled = config.UsernamePrefixEnabled,
109 | GroupNamePrefixEnabled = config.GroupNamePrefixEnabled,
110 | AuthorizationCodePrompt = config.AuthorizationCodePrompt,
111 | DomainHint = config.DomainHint
112 | };
113 | }
114 |
115 | public static void SaveGeneralSettings(string service, int portalId, AzureADProviderSettings settings)
116 | {
117 | var config = new AzureConfig(service, portalId)
118 | {
119 | TenantId = settings.TenantId,
120 | APIKey = settings.ApiKey,
121 | APISecret = settings.ApiSecret,
122 | RedirectUri = settings.RedirectUri,
123 | OnErrorUri = settings.OnErrorUri,
124 | AutoRedirect = settings.AutoRedirect,
125 | AutoAuthorize = settings.AutoAuthorize,
126 | AutoMatchExistingUsers = settings.AutoMatchExistingUsers,
127 | Enabled = settings.Enabled,
128 | UseGlobalSettings = settings.UseGlobalSettings
129 | };
130 |
131 | AzureConfig.UpdateConfig(config);
132 | }
133 |
134 | public static void SaveAdvancedSyncSettings(string service, int portalId, AzureADProviderSettings settings)
135 | {
136 | var config = new AzureConfig(service, portalId)
137 | {
138 | AADTenantId = settings.AadTenantId,
139 | AADApplicationId = settings.AadAppClientId,
140 | AADApplicationKey = settings.AadAppSecret,
141 | GraphUseCustomParams = settings.GraphUseCustomParams,
142 | RoleSyncEnabled = settings.RoleSyncEnabled,
143 | UserSyncEnabled = settings.UserSyncEnabled,
144 | ProfileSyncEnabled = settings.ProfileSyncEnabled,
145 | UsernamePrefixEnabled = settings.UsernamePrefixEnabled,
146 | GroupNamePrefixEnabled = settings.GroupNamePrefixEnabled
147 | };
148 |
149 | AzureConfig.UpdateConfig(config);
150 | }
151 | public static void SaveAdvancedMoreSettings(string service, int portalId, AzureADProviderSettings settings)
152 | {
153 | var config = new AzureConfig(service, portalId)
154 | {
155 | JwtAudiences = settings.JwtAudiences,
156 | APIResource = settings.ApiResource + (!string.IsNullOrEmpty(settings.ApiResource.Trim()) && !settings.ApiResource.EndsWith("/") ? "/" : ""),
157 | Scopes = settings.Scopes,
158 | AuthorizationCodePrompt = settings.AuthorizationCodePrompt,
159 | DomainHint = settings.DomainHint
160 | };
161 |
162 | AzureConfig.UpdateConfig(config);
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------