diff --git a/apps/dashboard/src/main/java/com/akto/action/HomeAction.java b/apps/dashboard/src/main/java/com/akto/action/HomeAction.java index c1bbb000da..5d84c442f7 100644 --- a/apps/dashboard/src/main/java/com/akto/action/HomeAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/HomeAction.java @@ -56,7 +56,7 @@ public String execute() { if (GithubLogin.getGithubUrl() != null) { servletRequest.setAttribute("githubUrl", GithubLogin.getGithubUrl()); } - if(OktaLogin.getAuthorisationUrl() != null){ + if(DashboardMode.isOnPremDeployment() && OktaLogin.getAuthorisationUrl() != null){ servletRequest.setAttribute("oktaAuthUrl", new String(Base64.getEncoder().encode(OktaLogin.getAuthorisationUrl().getBytes()))); } if (InitializerListener.aktoVersion != null && InitializerListener.aktoVersion.contains("akto-release-version")) { diff --git a/apps/dashboard/src/main/java/com/akto/action/SignupAction.java b/apps/dashboard/src/main/java/com/akto/action/SignupAction.java index 587a297ea3..1e15177698 100644 --- a/apps/dashboard/src/main/java/com/akto/action/SignupAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/SignupAction.java @@ -509,32 +509,38 @@ public String registerViaGithub() { } public String registerViaOkta() throws IOException{ - if (!DashboardMode.isOnPremDeployment()) return Action.ERROR.toUpperCase(); - OktaLogin oktaLoginInstance = OktaLogin.getInstance(); - if(oktaLoginInstance == null){ - servletResponse.sendRedirect("/login"); - return ERROR.toUpperCase(); - } + try { + Config.OktaConfig oktaConfig; + if(DashboardMode.isOnPremDeployment()) { + OktaLogin oktaLoginInstance = OktaLogin.getInstance(); + if(oktaLoginInstance == null){ + servletResponse.sendRedirect("/login"); + return ERROR.toUpperCase(); + } - Config.OktaConfig oktaConfig = OktaLogin.getInstance().getOktaConfig(); - if (oktaConfig == null) { - servletResponse.sendRedirect("/login"); - return ERROR.toUpperCase(); - } + setAccountId(1000000); + oktaConfig = OktaLogin.getInstance().getOktaConfig(); + } else { + setAccountId(Integer.parseInt(state)); + oktaConfig = Config.getOktaConfig(accountId); + } + if(oktaConfig == null) { + servletResponse.sendRedirect("/login"); + return ERROR.toUpperCase(); + } - String domainUrl = "https://" + oktaConfig.getOktaDomainUrl() + "/oauth2/" + oktaConfig.getAuthorisationServerId() + "/v1"; - String clientId = oktaConfig.getClientId(); - String clientSecret = oktaConfig.getClientSecret(); - String redirectUri = oktaConfig.getRedirectUri(); + String domainUrl = "https://" + oktaConfig.getOktaDomainUrl() + "/oauth2/" + oktaConfig.getAuthorisationServerId() + "/v1"; + String clientId = oktaConfig.getClientId(); + String clientSecret = oktaConfig.getClientSecret(); + String redirectUri = oktaConfig.getRedirectUri(); - BasicDBObject params = new BasicDBObject(); - params.put("grant_type", "authorization_code"); - params.put("code", this.code); - params.put("client_id", clientId); - params.put("client_secret", clientSecret); - params.put("redirect_uri", redirectUri); + BasicDBObject params = new BasicDBObject(); + params.put("grant_type", "authorization_code"); + params.put("code", this.code); + params.put("client_id", clientId); + params.put("client_secret", clientSecret); + params.put("redirect_uri", redirectUri); - try { Map tokenData = CustomHttpRequest.postRequestEncodedType(domainUrl +"/token",params); String accessToken = tokenData.get("access_token").toString(); Map userInfo = CustomHttpRequest.getRequest( domainUrl + "/userinfo","Bearer " + accessToken); @@ -544,7 +550,7 @@ public String registerViaOkta() throws IOException{ SignupInfo.OktaSignupInfo oktaSignupInfo= new SignupInfo.OktaSignupInfo(accessToken, username); shouldLogin = "true"; - createUserAndRedirect(email, username, oktaSignupInfo, 1000000, Config.ConfigType.OKTA.toString()); + createUserAndRedirect(email, username, oktaSignupInfo, accountId, Config.ConfigType.OKTA.toString(), RBAC.Role.MEMBER); code = ""; } catch (Exception e) { loggerMaker.errorAndAddToDb("Error while signing in via okta sso \n" + e.getMessage(), LogDb.DASHBOARD); @@ -560,7 +566,7 @@ public String registerViaOkta() throws IOException{ public String sendRequestToSamlIdP() throws IOException{ String queryString = servletRequest.getQueryString(); String emailId = Util.getValueFromQueryString(queryString, "email"); - if(emailId.length() == 0){ + if(emailId.isEmpty()){ code = "Error, user email cannot be empty"; logger.error(code); servletResponse.sendRedirect("/login"); @@ -569,11 +575,10 @@ public String sendRequestToSamlIdP() throws IOException{ logger.info("Trying to sign in for: " + emailId); setUserEmail(emailId); SAMLConfig samlConfig = SSOConfigsDao.instance.getSSOConfig(userEmail); - if(samlConfig == null){ - code = "Error, cannot login via SSO, redirecting to login"; + if(samlConfig == null) { + code = "Error, cannot login via SSO, trying to login with okta sso"; logger.error(code); - servletResponse.sendRedirect("/login"); - return ERROR.toUpperCase(); + return oktaAuthUrlCreator(emailId); } int tempAccountId = Integer.parseInt(samlConfig.getId()); logger.info("Account id: " + tempAccountId + " found for " + emailId); @@ -599,6 +604,21 @@ public String sendRequestToSamlIdP() throws IOException{ return SUCCESS.toUpperCase(); } + public String oktaAuthUrlCreator(String emailId) throws IOException { + logger.info("Trying to create auth url for okta sso for: " + emailId); + Config.OktaConfig oktaConfig = Config.getOktaConfig(emailId); + if(oktaConfig == null) { + code= "Error, cannot find okta sso for this organization, redirecting to login"; + logger.error(code); + servletResponse.sendRedirect("/login"); + return ERROR.toUpperCase(); + } + + String authorisationUrl = OktaLogin.getAuthorisationUrl(emailId); + servletResponse.sendRedirect(authorisationUrl); + return SUCCESS.toUpperCase(); + } + public String registerViaAzure() throws Exception{ Auth auth; try { diff --git a/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java b/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java index 23dec2273f..719c9a01d9 100644 --- a/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java +++ b/apps/dashboard/src/main/java/com/akto/action/user/OktaSsoAction.java @@ -24,12 +24,6 @@ public class OktaSsoAction extends UserAction { private String redirectUri; public String addOktaSso() { - - if(!DashboardMode.isOnPremDeployment()){ - addActionError("This feature is only available in on-prem deployment"); - return ERROR.toUpperCase(); - } - if (SsoUtils.isAnySsoActive()) { addActionError("A SSO Integration already exists."); return ERROR.toUpperCase(); @@ -41,20 +35,30 @@ public String addOktaSso() { oktaConfig.setAuthorisationServerId(authorisationServerId); oktaConfig.setOktaDomainUrl(oktaDomain); oktaConfig.setRedirectUri(redirectUri); - + if(!DashboardMode.isOnPremDeployment()){ + oktaConfig.setAccountId(Context.accountId.get()); + String userLogin = getSUser().getLogin(); + String domain = userLogin.split("@")[1]; + oktaConfig.setOrganizationDomain(domain); + } ConfigsDao.instance.insertOne(oktaConfig); return SUCCESS.toUpperCase(); } public String deleteOktaSso() { - if(!DashboardMode.isOnPremDeployment()){ - addActionError("This feature is only available in on-prem deployment"); - return ERROR.toUpperCase(); + DeleteResult result; + if(DashboardMode.isOnPremDeployment()) { + result = ConfigsDao.instance.deleteAll(Filters.eq("_id", "OKTA-ankush")); + } else { + result = ConfigsDao.instance.deleteAll( + Filters.and( + Filters.eq("_id", "OKTA-ankush"), + Filters.eq(Config.OktaConfig.ACCOUNT_ID, Context.accountId.get()) + ) + ); } - DeleteResult result = ConfigsDao.instance.deleteAll(Filters.eq("_id", "OKTA-ankush")); - if (result.getDeletedCount() > 0) { for (Object obj : UsersDao.instance.getAllUsersInfoForTheAccount(Context.accountId.get())) { BasicDBObject detailsObj = (BasicDBObject) obj; @@ -68,13 +72,13 @@ public String deleteOktaSso() { @Override public String execute() throws Exception { - - if(!DashboardMode.isOnPremDeployment()){ - addActionError("This feature is only available in on-prem deployment"); - return ERROR.toUpperCase(); + Config.OktaConfig oktaConfig; + if(DashboardMode.isOnPremDeployment()) { + oktaConfig = (Config.OktaConfig) ConfigsDao.instance.findOne("_id", "OKTA-ankush"); + } else { + String email = getSUser().getLogin(); + oktaConfig = Config.getOktaConfig(email); } - - Config.OktaConfig oktaConfig = (Config.OktaConfig) ConfigsDao.instance.findOne("_id", "OKTA-ankush"); if (SsoUtils.isAnySsoActive() && oktaConfig == null) { addActionError("A different SSO Integration already exists."); return ERROR.toUpperCase(); diff --git a/apps/dashboard/src/main/java/com/akto/utils/OktaLogin.java b/apps/dashboard/src/main/java/com/akto/utils/OktaLogin.java index aec09a1a79..317690ae59 100644 --- a/apps/dashboard/src/main/java/com/akto/utils/OktaLogin.java +++ b/apps/dashboard/src/main/java/com/akto/utils/OktaLogin.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; import com.akto.dao.ConfigsDao; @@ -55,6 +54,22 @@ public static String getAuthorisationUrl() { return authUrl; } + public static String getAuthorisationUrl(String email) { + OktaConfig oktaConfig = Config.getOktaConfig(email); + + Map paramMap = new HashMap<>(); + paramMap.put("client_id", oktaConfig.getClientId()); + paramMap.put("redirect_uri",oktaConfig.getRedirectUri()); + paramMap.put("response_type", "code"); + paramMap.put("scope", "openid%20email%20profile"); + paramMap.put("state", String.valueOf(oktaConfig.getAccountId())); + + String queryString = SsoUtils.getQueryString(paramMap); + + String authUrl = "https://" + oktaConfig.getOktaDomainUrl() + "/oauth2/" + oktaConfig.getAuthorisationServerId() + "/v1/authorize?" + queryString; + return authUrl; + } + private OktaLogin() { } diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/integrations/OktaIntegration.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/integrations/OktaIntegration.jsx index 8375b7ff12..21fa86632c 100644 --- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/integrations/OktaIntegration.jsx +++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/settings/integrations/OktaIntegration.jsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react' import CopyCommand from '../../../components/shared/CopyCommand'; import IntegrationsLayout from './IntegrationsLayout'; -import { Button, Form, FormLayout, HorizontalStack, LegacyCard, Text, TextField } from '@shopify/polaris'; +import { Button, Form, FormLayout, HorizontalStack, LegacyCard, Link, Text, TextField, VerticalStack } from '@shopify/polaris'; import func from "@/util/func" import settingRequests from '../api'; import SpinnerCentered from "../../../components/progress/SpinnerCentered" @@ -22,7 +22,7 @@ function OktaIntegration() { const [oktaDomain, setOktaDomain] = useState('') const [authorizationServerId, setAuthorizationServerId] = useState('') const [showDeleteModal, setShowDeleteModal] = useState(false); - const [nextButtonActive,setNextButtonActive] = useState(window.DASHBOARD_MODE === "ON_PREM") + const [nextButtonActive,setNextButtonActive] = useState(true) const redirectUri = hostname + "/authorization-code/callback" @@ -135,6 +135,19 @@ function OktaIntegration() { },[]) const cardContent = "Enable login via Okta SSO in your dashboard." + + const useCardContent = ( + + {cardContent} + + Use + https://app.akto.io/sso-login + for signing into AKTO dashboard via SSO. + + + ) + + const oktaSSOComponent = ( loading ? : @@ -145,7 +158,7 @@ function OktaIntegration() { return ( <> - + ) diff --git a/libs/dao/src/main/java/com/akto/dto/Config.java b/libs/dao/src/main/java/com/akto/dto/Config.java index bb652dea71..570346bed7 100644 --- a/libs/dao/src/main/java/com/akto/dto/Config.java +++ b/libs/dao/src/main/java/com/akto/dto/Config.java @@ -4,6 +4,8 @@ import java.util.HashSet; import java.util.Set; +import com.akto.dao.ConfigsDao; +import com.mongodb.client.model.Filters; import org.bson.codecs.pojo.annotations.BsonDiscriminator; @BsonDiscriminator @@ -356,7 +358,11 @@ public static class OktaConfig extends Config { private String oktaDomainUrl; private String authorisationServerId; private String redirectUri; - + public static final String ORGANIZATION_DOMAIN = "organizationDomain"; + private String organizationDomain; + public static final String ACCOUNT_ID = "accountId"; + private int accountId; + public static final String CONFIG_ID = ConfigType.OKTA.name() + CONFIG_SALT; public OktaConfig() { @@ -399,6 +405,20 @@ public String getRedirectUri() { public void setRedirectUri(String redirectUri) { this.redirectUri = redirectUri; } + + public String getOrganizationDomain() { + return organizationDomain; + } + public void setOrganizationDomain(String organizationDomain) { + this.organizationDomain = organizationDomain; + } + + public int getAccountId() { + return accountId; + } + public void setAccountId(int accountId) { + this.accountId = accountId; + } } @BsonDiscriminator @@ -664,4 +684,30 @@ public static boolean isConfigSSOType(ConfigType configType){ } return ssoConfigTypes.contains(configType); } + + public static OktaConfig getOktaConfig(int accountId) { + OktaConfig config = (OktaConfig) ConfigsDao.instance.findOne( + Filters.and( + Filters.eq("_id", "OKTA-ankush"), + Filters.eq(OktaConfig.ACCOUNT_ID, accountId) + ) + ); + return config; + } + + public static OktaConfig getOktaConfig(String userEmail){ + if (userEmail == null || userEmail.trim().isEmpty()) { + return null; + } + String[] companyKeyArr = userEmail.split("@"); + if(companyKeyArr == null || companyKeyArr.length < 2){ + return null; + } + + String domain = companyKeyArr[1]; + OktaConfig config = (OktaConfig) ConfigsDao.instance.findOne( + Filters.eq(OktaConfig.ORGANIZATION_DOMAIN, domain) + ); + return config; + } }