/*
* Copyright 2016 predic8 GmbH, www.predic8.com
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.predic8.membrane.core.interceptor.oauth2;
import com.predic8.membrane.core.Constants;
import com.predic8.membrane.core.HttpRouter;
import com.predic8.membrane.core.Router;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.http.Header;
import com.predic8.membrane.core.http.Request;
import com.predic8.membrane.core.interceptor.authentication.session.SessionManager;
import com.predic8.membrane.core.interceptor.authentication.session.StaticUserDataProvider;
import com.predic8.membrane.core.interceptor.oauth2.authorizationservice.MembraneAuthorizationService;
import com.predic8.membrane.core.util.Util;
import com.predic8.membrane.core.util.functionalInterfaces.Consumer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runners.Parameterized;
import javax.mail.internet.ParseException;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.regex.Pattern;
public abstract class OAuth2AuthorizationServerInterceptorBase {
static Router router;
static Exchange exc;
static OAuth2AuthorizationServerInterceptor oasi;
static MembraneAuthorizationService mas;
static StaticUserDataProvider.User johnsUserData;
static Map<String,String> afterLoginMockParams;
static String afterCodeGenerationCode;
static String afterTokenGenerationToken;
static String afterTokenGenerationTokenType;
static Consumer<Exchange> noPostprocessing() {
return new Consumer<Exchange>() {
@Override
public void call(Exchange exchange) {
return;
}
};
}
static Runnable noPreprocessing() {
return new Runnable() {
@Override
public void run() {
return;
}
};
}
public static Callable<Exchange> getMockAuthRequestExchange() throws Exception {
return new Callable<Exchange>() {
@Override
public Exchange call() throws Exception {
Exchange exc = new Request.Builder().get(mas.getLoginURL("123security","http://localhost:2001/", "/")).buildExchange();
exc.getRequest().getHeader().add("Cookie",oasi.getSessionManager().getCookieName() + "=" + OAuth2TestUtil.sessionId);
return exc;
}
};
}
public static Consumer<Exchange> loginAsJohn(){
return new Consumer<Exchange>() {
@Override
public void call(Exchange exchange) {
SessionManager.Session session = oasi.getSessionManager().getOrCreateSession(exchange);
OAuth2TestUtil.sessionId = exchange.getResponse().getHeader().getFirstValue("Set-Cookie").split(Pattern.quote("="))[1].split(Pattern.quote(";"))[0];
session.preAuthorize("john", afterLoginMockParams);
}
};
}
public static Callable<Exchange> getMockEmptyEndpointRequest() throws Exception {
return new Callable<Exchange>() {
@Override
public Exchange call() throws Exception {
Exchange exc = new Request.Builder().get("/").buildExchange();
exc.getRequest().getHeader().add("Cookie",oasi.getSessionManager().getCookieName() + "=" + OAuth2TestUtil.sessionId);
OAuth2TestUtil.makeExchangeValid(exc);
return exc;
}
};
}
static Consumer<Exchange> getCodeFromResponse() {
return new Consumer<Exchange>() {
@Override
public void call(Exchange exc) {
String loc = exc.getResponse().getHeader().getFirstValue("Location");
for(String s1 : loc.split(Pattern.quote("?"))){
if(s1.startsWith("code=")){
for(String s2 : s1.split("&")){
if(s2.startsWith("code="))
afterCodeGenerationCode = s2.substring(5);
break;
}
}
}
}
};
}
public static Callable<Exchange> getMockTokenRequest() throws Exception {
return new Callable<Exchange>() {
@Override
public Exchange call() throws Exception {
return new Request.Builder()
.post(mas.getTokenEndpoint())
.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded")
.header(Header.ACCEPT, "application/json")
.header(Header.USER_AGENT, Constants.USERAGENT)
.body("code=" + afterCodeGenerationCode
+ "&client_id=" + mas.getClientId()
+ "&client_secret=" + mas.getClientSecret()
+ "&redirect_uri=" + "http://localhost:2001/" + "oauth2callback"
+ "&grant_type=authorization_code")
.buildExchange();
}
};
}
static Consumer<Exchange> getTokenAndTokenTypeFromResponse() throws IOException, ParseException {
return new Consumer<Exchange>() {
@Override
public void call(Exchange exc) throws Exception {
HashMap<String, String> json = Util.parseSimpleJSONResponse(exc.getResponse());
afterTokenGenerationToken = json.get("access_token");
afterTokenGenerationTokenType = json.get("token_type");
}
};
}
public static Callable<Exchange> getMockUserinfoRequest() throws Exception {
return new Callable<Exchange>() {
@Override
public Exchange call() throws Exception {
return new Request.Builder()
.get(mas.getUserInfoEndpoint())
.header("Authorization", afterTokenGenerationTokenType + " " + afterTokenGenerationToken)
.header("User-Agent", Constants.USERAGENT)
.header(Header.ACCEPT, "application/json")
.buildExchange();
}
};
}
public static Runnable runUntilGoodTokenRequest() {
return runTest(OAuth2AuthorizationServerInterceptorNormalTest.class,"testGoodTokenRequest");
}
public static Runnable runUntilGoodGrantedAuthCode() {
return runTest(OAuth2AuthorizationServerInterceptorNormalTest.class,"testGoodGrantedAuthCode");
}
public static Runnable runUntilGoodAuthRequest() {
return runTest(OAuth2AuthorizationServerInterceptorNormalTest.class,"testGoodAuthRequest");
}
public static Runnable runUntilGoodTokenOpenidRequest() {
return runTest(OAuth2AuthorizationServerInterceptorOpenidTest.class,"testGoodTokenRequest");
}
public static Runnable runUntilGoodGrantedAuthCodeOpenid() {
return runTest(OAuth2AuthorizationServerInterceptorOpenidTest.class,"testGoodGrantedAuthCode");
}
public static Runnable runUntilGoodAuthOpenidRequest() {
return runTest(OAuth2AuthorizationServerInterceptorOpenidTest.class,"testGoodAuthRequest");
}
@Before
public void setUp() throws Exception{
router = new HttpRouter();
initOasi();
initMas();
initLoginMockParametersForJohn();
}
@Parameterized.Parameters(name = "{0}")
public static Collection<Object[]> data() throws Exception {
return Arrays.asList(new Object[][] {
});
}
@Parameterized.Parameter
public String testName;
@Parameterized.Parameter(value = 1)
public Runnable preprocessing;
@Parameterized.Parameter(value = 2)
public Callable<Exchange> preparedExchange;
@Parameterized.Parameter(value = 3)
public int expectedStatusCode;
@Parameterized.Parameter(value = 4)
public Consumer<Exchange> postprocessing;
@Test
public void test() throws Exception {
preprocessing.run();
exc = preparedExchange.call();
OAuth2TestUtil.makeExchangeValid(exc);
oasi.handleRequest(exc);
Assert.assertEquals(expectedStatusCode,exc.getResponse().getStatusCode());
postprocessing.call(exc);
}
protected static <T>Runnable runTest(final Class<T> caller, final String name){
return new Runnable() {
@Override
public void run() {
try {
List<Object[]> allParams = (List<Object[]>) caller.getMethod("data").invoke(null);
Object[] params = null;
for (Object[] p : allParams) {
if (name.equals(p[0])){
params = p;
break;
}
}
Runnable preprocessing = (Runnable) params[1];
Callable<Exchange> preparedExchange = (Callable<Exchange>) params[2];
int expectedStatusCode = (Integer) params[3];
Consumer<Exchange> postprocessing = (Consumer<Exchange>) params[4];
preprocessing.run();
Exchange exc = preparedExchange.call();
OAuth2TestUtil.makeExchangeValid(exc);
oasi.handleRequest(exc);
Assert.assertEquals(expectedStatusCode, exc.getResponse().getStatusCode());
postprocessing.call(exc);
}catch(Exception e){
e.printStackTrace();
}
}
};
}
private void initLoginMockParametersForJohn() {
afterLoginMockParams = new HashMap<String, String>();
afterLoginMockParams.put("response_type","code");
afterLoginMockParams.put("scope","profile");
afterLoginMockParams.put("redirect_uri","http://localhost:2001/oauth2callback");
afterLoginMockParams.put("state", "security_token=123&url=/");
afterLoginMockParams.put("client_id", "abc");
afterLoginMockParams.putAll(johnsUserData.getAttributes());
}
private void initMas() throws Exception {
mas = new MembraneAuthorizationService();
mas.setClientId("abc");
mas.setClientSecret("def");
mas.setSrc(System.getProperty("user.dir") + "\\src\\test\\resources\\oauth2");
mas.init(router);
}
private void initOasi() throws Exception {
oasi = new OAuth2AuthorizationServerInterceptor();
setOasiUserDataProvider();
setOasiClientList();
setOasiClaimList();
setOasiProperties();
oasi.init(router);
}
private void setOasiProperties() {
oasi.setLocation("src\\test\\resources\\oauth2\\loginDialog\\dialog");
oasi.setPath("/login/");
oasi.setIssuer("http://Localhost:2001");
}
private void setOasiClaimList() {
ClaimList cl = new ClaimList();
cl.setValue("username email sub");
ArrayList<ClaimList.Scope> scopes = new ArrayList<ClaimList.Scope>();
ClaimList.Scope scope = new ClaimList.Scope("profile","username email");
scopes.add(scope);
cl.setScopes(scopes);
oasi.setClaimList(cl);
}
private void setOasiClientList() {
StaticClientList cl = new StaticClientList();
ArrayList<Client> clients = new ArrayList<Client>();
Client john2 = new Client("abc","def","http://localhost:2001/oauth2callback");
clients.add(john2);
cl.setClients(clients);
oasi.setClientList(cl);
}
private void setOasiUserDataProvider() {
StaticUserDataProvider udp = new StaticUserDataProvider();
ArrayList<StaticUserDataProvider.User> users = new ArrayList<StaticUserDataProvider.User>();
johnsUserData = new StaticUserDataProvider.User("john", "password");
johnsUserData.getAttributes().put("email","e@mail.com");
users.add(johnsUserData);
udp.setUsers(users);
oasi.setUserDataProvider(udp);
}
}