/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.login.oauth.spi; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.scribe.builder.api.DefaultApi20; import org.scribe.extractors.AccessTokenExtractor; import org.scribe.model.OAuthConfig; import org.scribe.model.Token; import org.scribe.model.Verb; import org.scribe.model.Verifier; import org.scribe.oauth.OAuth20ServiceImpl; import org.scribe.oauth.OAuthService; import org.scribe.utils.OAuthEncoder; /** * * Initial date: 6 oct. 2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class OpenIdConnectFullConfigurableApi extends DefaultApi20 { private static final OLog log = Tracing.createLoggerFor(OpenIdConnectFullConfigurableApi.class); private final OpenIdConnectFullConfigurableProvider provider; public OpenIdConnectFullConfigurableApi(OpenIdConnectFullConfigurableProvider provider) { this.provider = provider; } @Override public String getAccessTokenEndpoint() { return null; } @Override public AccessTokenExtractor getAccessTokenExtractor() { return null; } @Override public String getAuthorizationUrl(OAuthConfig config) { String url = provider.getEndPoint(); StringBuilder authorizeUrl = new StringBuilder(); authorizeUrl .append(url).append("?") .append("response_type=").append(OAuthEncoder.encode("id_token token")) .append("&client_id=").append(config.getApiKey()) .append("&redirect_uri=").append(OAuthEncoder.encode(config.getCallback())) .append("&scope=").append(OAuthEncoder.encode("openid email")) .append("&state=").append(UUID.randomUUID().toString()) .append("&nonce=").append(UUID.randomUUID().toString()); return authorizeUrl.toString(); } @Override public Verb getAccessTokenVerb() { return Verb.POST; } @Override public OAuthService createService(OAuthConfig config) { return new OpenIdConnectFullConfigurableService(this, config); } public class OpenIdConnectFullConfigurableService extends OAuth20ServiceImpl { public OpenIdConnectFullConfigurableService(DefaultApi20 api, OAuthConfig config) { super(api, config); } @Override public Token getAccessToken(Token requestToken, Verifier verifier) { try { OpenIDVerifier oVerifier = (OpenIDVerifier)verifier; String idToken = oVerifier.getIdToken(); JSONObject idJson = JSONWebToken.parse(idToken).getJsonPayload(); JSONObject accessJson = JSONWebToken.parse(oVerifier.getAccessToken()).getJsonPayload(); boolean allOk = true; if(!provider.getIssuer().equals(idJson.get("iss"))) { allOk &= false; log.error("iss don't match issuer"); } if(!provider.getIssuer().equals(accessJson.get("iss"))) { allOk &= false; log.error("iss don't match issuer"); } if(!provider.getAppKey().equals(idJson.get("aud"))) { allOk &= false; log.error("aud don't match application key"); } if(!oVerifier.getState().equals(oVerifier.getSessionState())) { allOk &= false; log.error("state doesn't match session state"); } if(!oVerifier.getSessionNonce().equals(idJson.get("nonce"))) { allOk &= false; log.error("session nonce don't match verifier nonce"); } return allOk ? new Token(idToken, oVerifier.getState()) : null; } catch (JSONException e) { log.error("", e); return null; } } } }