Skip to content

Commit

Permalink
Merge pull request #2078 from akto-api-security/hotfix/sso_login_dire…
Browse files Browse the repository at this point in the history
…ctly_in_login_page

Hotfix/sso login directly in login page
  • Loading branch information
Ark2307 authored Feb 10, 2025
2 parents 92bcced + beadf3d commit 1efbeb2
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 70 deletions.
30 changes: 21 additions & 9 deletions apps/dashboard/src/main/java/com/akto/action/HomeAction.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.akto.action;

import com.akto.dao.SSOConfigsDao;
import com.akto.dao.UsersDao;
import com.akto.dto.Config;
import com.akto.dto.User;
import com.akto.listener.InitializerListener;
import com.akto.utils.*;
Expand All @@ -21,7 +23,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;

import static com.akto.action.SignupAction.*;
Expand Down Expand Up @@ -50,15 +51,26 @@ public String verifyEmail(){
public String execute() {

servletRequest.setAttribute("isSaas", InitializerListener.isSaas);
if (GithubLogin.getClientId() != null) {
servletRequest.setAttribute("githubClientId", new String(Base64.getEncoder().encode(GithubLogin.getClientId().getBytes())));
}
if (GithubLogin.getGithubUrl() != null) {
servletRequest.setAttribute("githubUrl", GithubLogin.getGithubUrl());
}
if(DashboardMode.isOnPremDeployment() && OktaLogin.getAuthorisationUrl() != null){
servletRequest.setAttribute("oktaAuthUrl", new String(Base64.getEncoder().encode(OktaLogin.getAuthorisationUrl().getBytes())));
if(DashboardMode.isOnPremDeployment()){
if (GithubLogin.getGithubUrl() != null) {
servletRequest.setAttribute("githubAuthUrl", GithubLogin.getGithubUrl() + "/login/oauth/authorize?client_id=" + GithubLogin.getClientId() + "&scope=user&state=1000000");
servletRequest.setAttribute("activeSso", Config.ConfigType.GITHUB);
}

if (OktaLogin.getAuthorisationUrl() != null) {
servletRequest.setAttribute("oktaAuthUrl", OktaLogin.getAuthorisationUrl());
servletRequest.setAttribute("activeSso", Config.ConfigType.OKTA);
}

if (SSOConfigsDao.getSAMLConfigByAccountId(1000000, Config.ConfigType.AZURE) != null) {
servletRequest.setAttribute("activeSso", Config.ConfigType.AZURE);
}

if (SSOConfigsDao.getSAMLConfigByAccountId(1000000, Config.ConfigType.GOOGLE_SAML) != null) {
servletRequest.setAttribute("activeSso", Config.ConfigType.GOOGLE_SAML);
}
}

if (InitializerListener.aktoVersion != null && InitializerListener.aktoVersion.contains("akto-release-version")) {
servletRequest.setAttribute("AktoVersionGlobal", "");
} else {
Expand Down
73 changes: 42 additions & 31 deletions apps/dashboard/src/main/java/com/akto/action/SignupAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ public String registerViaGithub() {
params.put("client_id", githubConfig.getClientId());
params.put("client_secret", githubConfig.getClientSecret());
params.put("code", this.code);
params.put("scope", "user");
logger.info("Github code length: {}", this.code.length());
try {
String githubUrl = githubConfig.getGithubUrl();
Expand Down Expand Up @@ -491,12 +492,17 @@ public String registerViaGithub() {
int refreshTokenExpiry = (int) Double.parseDouble(tokenData.getOrDefault("refresh_token_expires_in", "0").toString());
Map<String,Object> userData = CustomHttpRequest.getRequest(githubApiUrl + "/user", "Bearer " + accessToken);
logger.info("Get request to {} success", githubApiUrl);
String company = "sso";
String username = userData.get("login").toString() + "@" + company;

List<Map<String, String>> emailResp = GithubLogin.getEmailRequest(accessToken);
String username = userData.get("name").toString();
String email = GithubLogin.getPrimaryGithubEmail(emailResp);
if(email == null || email.isEmpty()) {
email = username + "@sso";
}
logger.info("username {}", username);
SignupInfo.GithubSignupInfo ghSignupInfo = new SignupInfo.GithubSignupInfo(accessToken, refreshToken, refreshTokenExpiry, username);
SignupInfo.GithubSignupInfo ghSignupInfo = new SignupInfo.GithubSignupInfo(accessToken, refreshToken, refreshTokenExpiry, email, username);
shouldLogin = "true";
createUserAndRedirect(username, username, ghSignupInfo, 1000000, Config.ConfigType.GITHUB.toString());
createUserAndRedirectWithDefaultRole(email, username, ghSignupInfo, 1000000, Config.ConfigType.GITHUB.toString());
code = "";
logger.info("Executed registerViaGithub");

Expand All @@ -520,8 +526,12 @@ public String registerViaOkta() throws IOException{
servletResponse.sendRedirect("/login");
return ERROR.toUpperCase();
}

setAccountId(1000000);
try {
setAccountId(Integer.parseInt(state));
} catch (NumberFormatException e) {
servletResponse.sendRedirect("/login");
return ERROR.toUpperCase();
}
oktaConfig = OktaLogin.getInstance().getOktaConfig();
} else {
setAccountId(Integer.parseInt(state));
Expand Down Expand Up @@ -551,14 +561,8 @@ public String registerViaOkta() throws IOException{
String username = userInfo.get("preferred_username").toString();

SignupInfo.OktaSignupInfo oktaSignupInfo= new SignupInfo.OktaSignupInfo(accessToken, username);

String defaultRole = RBAC.Role.MEMBER.name();
if (UsageMetricCalculator.isRbacFeatureAvailable(accountId)) {
defaultRole = fetchDefaultInviteRole(accountId, RBAC.Role.GUEST.name());
}

shouldLogin = "true";
createUserAndRedirect(email, username, oktaSignupInfo, accountId, Config.ConfigType.OKTA.toString(), defaultRole);
createUserAndRedirectWithDefaultRole(email, username, oktaSignupInfo, accountId, Config.ConfigType.OKTA.toString());
code = "";
} catch (Exception e) {
loggerMaker.errorAndAddToDb("Error while signing in via okta sso \n" + e.getMessage(), LogDb.DASHBOARD);
Expand Down Expand Up @@ -587,15 +591,20 @@ public String fetchDefaultInviteRole(int accountId, String fallbackDefault){
public String sendRequestToSamlIdP() throws IOException{
String queryString = servletRequest.getQueryString();
String emailId = Util.getValueFromQueryString(queryString, "email");
if(emailId.isEmpty()){
if(!DashboardMode.isOnPremDeployment() && emailId.isEmpty()){
code = "Error, user email cannot be empty";
logger.error(code);
servletResponse.sendRedirect("/login");
return ERROR.toUpperCase();
}
logger.info("Trying to sign in for: " + emailId);
setUserEmail(emailId);
SAMLConfig samlConfig = SSOConfigsDao.instance.getSSOConfig(userEmail);
SAMLConfig samlConfig = null;
if(userEmail != null && !userEmail.isEmpty()) {
samlConfig = SSOConfigsDao.instance.getSSOConfig(userEmail);
} else if(DashboardMode.isOnPremDeployment()) {
samlConfig = SSOConfigsDao.getSAMLConfigByAccountId(1000000);
}
if(samlConfig == null) {
code = "Error, cannot login via SSO, trying to login with okta sso";
logger.error(code);
Expand Down Expand Up @@ -629,10 +638,13 @@ 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();
oktaConfig = OktaLogin.getInstance().getOktaConfig();
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);
Expand Down Expand Up @@ -681,12 +693,7 @@ public String registerViaAzure() throws Exception{
logger.info("Successful signing with Azure Idp for: "+ useremail);
SignupInfo.SamlSsoSignupInfo signUpInfo = new SignupInfo.SamlSsoSignupInfo(username, useremail, Config.ConfigType.AZURE);

String defaultRole = RBAC.Role.MEMBER.name();
if (UsageMetricCalculator.isRbacFeatureAvailable(this.accountId)) {
defaultRole = fetchDefaultInviteRole(this.accountId,RBAC.Role.GUEST.name());
}

createUserAndRedirect(useremail, username, signUpInfo, this.accountId, Config.ConfigType.AZURE.toString(), defaultRole);
createUserAndRedirectWithDefaultRole(useremail, username, signUpInfo, this.accountId, Config.ConfigType.AZURE.toString());
} catch (Exception e1) {
loggerMaker.errorAndAddToDb("Error while signing in via azure sso \n" + e1.getMessage(), LogDb.DASHBOARD);
servletResponse.sendRedirect("/login");
Expand Down Expand Up @@ -736,12 +743,7 @@ public String registerViaGoogleSamlSso() throws IOException{
shouldLogin = "true";
SignupInfo.SamlSsoSignupInfo signUpInfo = new SignupInfo.SamlSsoSignupInfo(username, userEmail, Config.ConfigType.GOOGLE_SAML);

String defaultRole = RBAC.Role.MEMBER.name();
if (UsageMetricCalculator.isRbacFeatureAvailable(this.accountId)) {
defaultRole = fetchDefaultInviteRole(this.accountId, RBAC.Role.GUEST.name());
}

createUserAndRedirect(userEmail, username, signUpInfo, this.accountId, Config.ConfigType.GOOGLE_SAML.toString(), defaultRole);
createUserAndRedirectWithDefaultRole(userEmail, username, signUpInfo, this.accountId, Config.ConfigType.GOOGLE_SAML.toString());
} catch (Exception e1) {
loggerMaker.errorAndAddToDb("Error while signing in via google workspace sso \n" + e1.getMessage(), LogDb.DASHBOARD);
servletResponse.sendRedirect("/login");
Expand Down Expand Up @@ -828,6 +830,15 @@ private void createUserAndRedirect(String userEmail, String username, SignupInfo
createUserAndRedirect(userEmail, username, signupInfo, invitationToAccount, method, null);
}

private void createUserAndRedirectWithDefaultRole(String userEmail, String username, SignupInfo signupInfo,
int invitationToAccount, String method) throws IOException {
String defaultRole = RBAC.Role.MEMBER.name();
if (UsageMetricCalculator.isRbacFeatureAvailable(invitationToAccount)) {
defaultRole = fetchDefaultInviteRole(invitationToAccount, RBAC.Role.GUEST.name());
}
createUserAndRedirect(userEmail, username, signupInfo, invitationToAccount, method, defaultRole);
}

private void createUserAndRedirect(String userEmail, String username, SignupInfo signupInfo,
int invitationToAccount, String method, String invitedRole) throws IOException {
loggerMaker.infoAndAddToDb("createUserAndRedirect called");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private SAMLConfig getConfig(ConfigType configType, String domain){
public String addSamlSsoInfo(){
String userLogin = getSUser().getLogin();
String domain = userLogin.split("@")[1];
if (SsoUtils.isAnySsoActive(Context.accountId.get())) {
if (SsoUtils.isAnySsoActive()) {
addActionError("A SSO Integration already exists.");
return ERROR.toUpperCase();
}
Expand Down Expand Up @@ -79,7 +79,7 @@ public String execute() throws Exception {
Filters.eq("configType", configType.name())
)
);
if (SsoUtils.isAnySsoActive(Context.accountId.get()) && samlConfig == null) {
if (SsoUtils.isAnySsoActive() && samlConfig == null) {
addActionError("A different SSO Integration already exists.");
return ERROR.toUpperCase();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.akto.dto.User;
import com.akto.dto.Config.OktaConfig;
import com.akto.util.Constants;
import com.akto.util.DashboardMode;
import com.akto.utils.sso.SsoUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
Expand Down Expand Up @@ -41,12 +40,10 @@ 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);
}
oktaConfig.setAccountId(Context.accountId.get());
String userLogin = getSUser().getLogin();
String domain = userLogin.split("@")[1];
oktaConfig.setOrganizationDomain(domain);
ConfigsDao.instance.insertOne(oktaConfig);

return SUCCESS.toUpperCase();
Expand Down
38 changes: 38 additions & 0 deletions apps/dashboard/src/main/java/com/akto/utils/GithubLogin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@
import com.akto.dao.context.Context;
import com.akto.dto.Config;
import com.akto.dto.Config.GithubConfig;
import com.akto.dto.OriginalHttpRequest;
import com.akto.dto.OriginalHttpResponse;
import com.akto.testing.ApiExecutor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;

public class GithubLogin {

public static final int PROBE_PERIOD_IN_SECS = 60;
private static GithubLogin instance = null;
private GithubConfig githubConfig = null;
private int lastProbeTs = 0;
public static final String GET_GITHUB_EMAILS_URL = "https://api.github.com/user/emails";

public static GithubLogin getInstance() {
boolean shouldProbeAgain = true;
Expand Down Expand Up @@ -52,6 +60,36 @@ public static String getGithubUrl() {
return githubUrl;
}

public static List<Map<String, String>> getEmailRequest(String accessToken){
ObjectMapper objectMapper = new ObjectMapper();
Map<String, List<String>> headers = new HashMap<>();
headers.put("Content-Type", Collections.singletonList("application/vnd.github+json"));
headers.put("Authorization", Collections.singletonList("Bearer " + accessToken));
headers.put("X-GitHub-Api-Version", Collections.singletonList("2022-11-28"));

OriginalHttpRequest request = new OriginalHttpRequest(GET_GITHUB_EMAILS_URL, "", "GET", null, headers, "");
OriginalHttpResponse response = null;
try {
response = ApiExecutor.sendRequest(request, false, null, false, new ArrayList<>());
return objectMapper.readValue(response.getBody(), new TypeReference<List<Map<String, String>>>() {});
}catch(Exception e){
return null;
}
}

public static String getPrimaryGithubEmail(List<Map<String, String>> emailResp){
if(emailResp == null){
return "";
}else{
for (Map<String, String> entryMap : emailResp) {
if(entryMap.get("primary").equals("true")){
return entryMap.get("email");
}
}
}
return null;
}

private GithubLogin() {
}

Expand Down
9 changes: 7 additions & 2 deletions apps/dashboard/src/main/java/com/akto/utils/OktaLogin.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public static OktaLogin getInstance() {
}

if (shouldProbeAgain) {
OktaConfig oktaConfig = (Config.OktaConfig) ConfigsDao.instance.findOne(Constants.ID, OktaConfig.getOktaId(Context.accountId.get()));
int accountId = Context.accountId.get() != null ? Context.accountId.get() : 1_000_000;
OktaConfig oktaConfig = (Config.OktaConfig) ConfigsDao.instance.findOne(Constants.ID, OktaConfig.getOktaId(accountId));
if (instance == null) {
instance = new OktaLogin();
}
Expand All @@ -47,7 +48,11 @@ public static String getAuthorisationUrl() {
paramMap.put("redirect_uri",oktaConfig.getRedirectUri());
paramMap.put("response_type", "code");
paramMap.put("scope", "openid%20email%20profile");
paramMap.put("state", "login");
int accountId = 1000000;
if(oktaConfig.getAccountId() != 0){
accountId = oktaConfig.getAccountId();
}
paramMap.put("state", String.valueOf(accountId));

String queryString = SsoUtils.getQueryString(paramMap);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public static boolean isAnySsoActive(){
}else{
List<String> ssoList = Arrays.asList(oktaIdString, "GITHUB-ankush", "AZURE-ankush");
Bson filter = Filters.in("_id", ssoList);
return ConfigsDao.instance.count(filter) > 0;
accountId = Context.accountId.get() != null ? Context.accountId.get() : 1_000_000;
return ConfigsDao.instance.count(filter) > 0 || isAnySsoActive(accountId);
}
}

Expand Down
6 changes: 5 additions & 1 deletion apps/dashboard/web/pages/login.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@
window.TIME_ZONE = '${requestScope.currentTimeZone}'
window.USER_FULL_NAME = '${requestScope.userFullName}'
window.ORGANIZATION_NAME = '${requestScope.organizationName}'
window.GOOGLE_SSO_URL=atob('${requestScope.googleSsoUrl}')
window.GOOGLE_SAML_AUTH_URL=atob('${requestScope.googleSamlAuthUrl}')
window.OKTA_AUTH_URL = '${requestScope.oktaAuthUrl}'
window.AZURE_AUTH_URL = '${requestScope.azureAuthUrl}'
window.GITHUB_AUTH_URL = '${requestScope.githubAuthUrl}'
window.ACTIVE_SSO = '${requestScope.activeSso}'
window.STIGG_IS_OVERAGE='${requestScope.stiggIsOverage}'
window.USAGE_PAUSED=JSON.parse('${requestScope.usagePaused}' || '{}');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function GithubSso() {
const [githubUrl, setGithubUrl] = useState("https://github.com")
const [githubApiUrl, setGithubApiUrl] = useState("https://api.github.com")

const [isModalDisabled, setIsModalDisabled] = useState(false)

const location = window.location ;
const hostname = location.origin;

Expand Down Expand Up @@ -44,10 +46,13 @@ function GithubSso() {
const addText = "Are you sure you want to add Github SSO Integration? This will enable all members of your GitHub account to access Akto dashboard."

const handleDeleteGithubSso = async () => {
setIsModalDisabled(true)
const response = await settingRequests.deleteGithubSso()
if (response) {
func.setToast(true, false, "Github SSO deleted successfully!")
setComponentType(0);
setShowGithubSsoModal(false)
setIsModalDisabled(false)
}
}

Expand All @@ -71,6 +76,7 @@ function GithubSso() {
}, [])

const handleAddGithubSso = async () => {
setIsModalDisabled(true)
const response = await settingRequests.addGithubSso(githubClientId, githubClientSecret, githubUrl, githubApiUrl)
if (response) {
if (response.error) {
Expand All @@ -79,6 +85,8 @@ function GithubSso() {
func.setToast(true, false, "Github SSO added successfully!")
window.location.reload()
}
setShowGithubSsoModal(false)
setIsModalDisabled(false)
}
}

Expand Down Expand Up @@ -123,7 +131,8 @@ function GithubSso() {
title="Are you sure?"
primaryAction={{
content: githubPresent ? 'Delete Github SSO' : 'Add GitHub SSO',
onAction: githubPresent ? handleDeleteGithubSso : handleAddGithubSso
onAction: githubPresent ? handleDeleteGithubSso : handleAddGithubSso,
disabled: isModalDisabled
}}
>
<Modal.Section>
Expand Down
Loading

0 comments on commit 1efbeb2

Please sign in to comment.