Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Egw upgrade #166

Open
wants to merge 8 commits into
base: egw-upgrade
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion components/security/auth-filter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,22 @@
<groupId>com.wso2telco.core</groupId>
<artifactId>dbutils</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.rest.api.util</artifactId>
<version>6.0.4</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version should be updated..

</dependency>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.impl</artifactId>
<version>6.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
</dependencies>

<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright (c) 2016, WSO2.Telco Inc. (http://www.wso2telco.com) All Rights Reserved.
* <p>
* WSO2.Telco Inc. licences this file to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wso2telco.core.authfilter.authentication;

import com.wso2telco.core.authfilter.util.AuthFilterParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.model.AccessTokenInfo;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.factory.KeyManagerHolder;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import javax.ws.rs.container.ContainerRequestContext;
import java.lang.reflect.Method;

public class BearerAuthenticator {
private static final String SUPER_TENANT_SUFFIX =
APIConstants.EMAIL_DOMAIN_SEPARATOR + MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
private static final Log log = LogFactory.getLog(BearerAuthenticator.class);

/**
* @param authorizationHeader Authorization Header value
* @return boolean
*/
public boolean isAuthenticatedUser(ContainerRequestContext requestContext, Method method, String
authorizationHeader) {
String accessToken = authorizationHeader
.replaceFirst(AuthFilterParam.AUTHENTICATION_SCHEME_BEARER.getTObject() + " ", "");
AccessTokenInfo tokenInfo = null;
try {
tokenInfo = KeyManagerHolder.getKeyManagerInstance().getTokenMetaData(accessToken);
} catch (APIManagementException e) {
log.error("Error while retrieving token information for token: " + accessToken, e);
}
// if we got valid access token we will proceed with next
if (tokenInfo != null && tokenInfo.isTokenValid()) {

//If scope validation successful then set tenant name and user name to current context
String tenantDomain = MultitenantUtils.getTenantDomain(tokenInfo.getEndUserName());
int tenantId;
PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RealmService realmService = (RealmService) carbonContext.getOSGiService(RealmService.class, null);
try {
String username = tokenInfo.getEndUserName();
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
if (username.endsWith(SUPER_TENANT_SUFFIX)) {
username = username.substring(0, username.length() - SUPER_TENANT_SUFFIX.length());
}
}
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
carbonContext.setTenantDomain(tenantDomain);
carbonContext.setTenantId(tenantId);
carbonContext.setUsername(username);
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
APIUtil.loadTenantConfigBlockingMode(tenantDomain);
}
return true;
} catch (org.wso2.carbon.user.api.UserStoreException e) {
log.error("Error while retrieving tenant id for tenant domain: " + tenantDomain, e);
}
} else {
log.error("Authentication failed. Please check your token");
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,35 @@ public boolean isAuthorizedRole(String userName, Set<String> allowedRolesSet) {
log.error("authorization failed for user : " + userName);
return false;
}

/**
* Checks the list of allowed scopes for a api resource against the scopes
* granted to a token
*
* @param currentTokenScopes Scopes granted to the token being evaluated
* @param allowedScopeSet Scopes allowed to access the APIs resource
* @return Boolean
*
*/
public Boolean isAuthorizedScope(String[] currentTokenScopes, Set<String> allowedScopeSet){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required to return a Boolean? Can't we simply send a boolean.


List<String> currentTokenScopesList = Arrays.asList(currentTokenScopes);

Iterator<String> iterator = allowedScopeSet.iterator();
while (iterator.hasNext()) {

String allowedScope = iterator.next();
if (currentTokenScopesList.contains(allowedScope)) {

return true;
}
}

if(log.isDebugEnabled()){
log.debug("Required OAuth Scopes: " + allowedScopeSet);
log.debug("Available OAuth Scopes: " + currentTokenScopesList);
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ public class AuthorizationFilterFactory extends AuthenticationProsser{

@Override
protected AuthenticationFilter loadFilter(String header) {

AuthenticationFilter authenticationFilter = null;

if (header.contains(AuthFilterParam.AUTHENTICATION_SCHEME_BASIC.getTObject())) {

authenticationFilter = new BasicAuthenticationFilter();
}


if (header.contains(AuthFilterParam.AUTHENTICATION_SCHEME_BEARER.getTObject())){
authenticationFilter = new BearerAuthenticationFilter();
}

return authenticationFilter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,106 +15,107 @@
******************************************************************************/
package com.wso2telco.core.authfilter.impl.authorization;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Response;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.wso2telco.core.authfilter.authentication.BasicAuthenticator;
import com.wso2telco.core.authfilter.authorization.UserAuthorizationValidator;
import com.wso2telco.core.authfilter.impl.AuthenticationFilter;
import com.wso2telco.core.authfilter.util.AuthFilterParam;
import com.wso2telco.core.authfilter.util.HeaderParam;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Response;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

public class BasicAuthenticationFilter implements AuthenticationFilter {

private final Log log = LogFactory.getLog(BasicAuthenticationFilter.class);
private final Log log = LogFactory.getLog(BasicAuthenticationFilter.class);

Response accessDenied = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource")
.build();
private BasicAuthenticator userAuthentication = new BasicAuthenticator();
private UserAuthorizationValidator userAuthorizationValidator = new UserAuthorizationValidator();

private String userName = null;

@Override
public boolean isAuthenticated(ContainerRequestContext requestContext, Method method, String authorizationHeader) {

Response accessDenied = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource")
.build();
private BasicAuthenticator userAuthentication = new BasicAuthenticator();
private UserAuthorizationValidator userAuthorizationValidator = new UserAuthorizationValidator();
String password = null;
boolean isAuthenticated = false;

private String userName = null;
// get base 64 encoded username and password
final String encodedUserPassword = authorizationHeader
.replaceFirst(AuthFilterParam.AUTHENTICATION_SCHEME_BASIC.getTObject() + " ", "");

@Override
public boolean isAuthenticated(ContainerRequestContext requestContext, Method method, String authorizationHeader) {
log.debug("base64 encoded username and password : " + encodedUserPassword);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap this with isDebugEnabled

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the implementation, already checking that condition. so better not to use duplicate conditions. it will increase the code line count as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Before being written to log condition will be checked. But while invoking method, the arguments will be evaluated, which in this case is a String concatenation. Usually we use debug logs abundantly, so more unguarded debug statements we use, more the String concatenations happen...


String password = null;
boolean isAuthenticated = false;

// get base 64 encoded username and password
final String encodedUserPassword = authorizationHeader
.replaceFirst(AuthFilterParam.AUTHENTICATION_SCHEME_BASIC.getTObject() + " ", "");
if (encodedUserPassword != null && encodedUserPassword.trim().length() > 0) {

log.debug("base64 encoded username and password : " + encodedUserPassword);
// decode username and password
String usernameAndPassword = new String(Base64.decodeBase64(encodedUserPassword.getBytes()));

if (encodedUserPassword != null && encodedUserPassword.trim().length() > 0) {
// split username and password by :
final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");

// decode username and password
String usernameAndPassword = new String(Base64.decodeBase64(encodedUserPassword.getBytes()));
if (tokenizer.countTokens() > 1) {

// split username and password by :
final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
userName = tokenizer.nextToken();
password = tokenizer.nextToken();

if (tokenizer.countTokens() > 1) {
log.debug("username : " + userName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap with isDebugEnabled

log.debug("password : " + password);

userName = tokenizer.nextToken();
password = tokenizer.nextToken();
// validate user authentication
isAuthenticated = userAuthentication.isAuthenticatedUser(userName, password);

log.debug("username : " + userName);
log.debug("password : " + password);
if (!isAuthenticated) {

// validate user authentication
isAuthenticated = userAuthentication.isAuthenticatedUser(userName, password);
requestContext.abortWith(accessDenied);
return false;
}
} else {

if (!isAuthenticated) {
requestContext.abortWith(accessDenied);
return false;
}
} else {

requestContext.abortWith(accessDenied);
return false;
}
} else {
requestContext.abortWith(accessDenied);
return false;
}

requestContext.abortWith(accessDenied);
return false;
}
} else {
return true;
}

requestContext.abortWith(accessDenied);
return false;
}
@Override
public boolean isAuthorized(ContainerRequestContext requestContext, Method method) {

return true;
}
boolean isAuthorized = false;

@Override
public boolean isAuthorized(ContainerRequestContext requestContext, Method method) {
requestContext.getHeaders().add(HeaderParam.USER_NAME.getTObject(), userName);

boolean isAuthorized = false;

requestContext.getHeaders().add(HeaderParam.USER_NAME.getTObject(), userName);

// validate user authorization by using user roles
if (method.isAnnotationPresent(RolesAllowed.class)) {
// validate user authorization by using user roles
if (method.isAnnotationPresent(RolesAllowed.class)) {

RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> allowedRolesSet = new HashSet<>(Arrays.asList(rolesAnnotation.value()));
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> allowedRolesSet = new HashSet<>(Arrays.asList(rolesAnnotation.value()));

isAuthorized = userAuthorizationValidator.isAuthorizedRole(userName, allowedRolesSet);
isAuthorized = userAuthorizationValidator.isAuthorizedRole(userName, allowedRolesSet);

if (!isAuthorized) {
if (!isAuthorized) {

requestContext.abortWith(accessDenied);
return false;
}
}
requestContext.abortWith(accessDenied);
return false;
}
}

return true;
}
return true;
}
}
Loading