001/*
002 *  Copyright 2022 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.extrausermgt.authentication.oidc;
017
018import java.io.InputStream;
019import java.net.URI;
020import java.net.URL;
021import java.nio.charset.StandardCharsets;
022import java.util.Map;
023
024import org.apache.commons.io.IOUtils;
025
026import org.ametys.runtime.authentication.AccessDeniedException;
027
028import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
029
030
031/**
032 * Sign in through an OIDC application (finding URIs by itself) using the OpenId Connect protocol.
033 */
034public class AutoDiscoveringOIDCCredentialProvider  extends AbstractOIDCCredentialProvider
035{
036    
037    /** 
038     * Returns the provider meta data which contains the URIs retrieved from the "/.well-known/openid-configuration" of the issuer
039     * @return The provider meta data which contains the URIs
040     */
041    private OIDCProviderMetadata _getProviderMetadata(URI issuerURI) throws Exception
042    {
043        URL providerConfigurationURL = issuerURI.resolve(".well-known/openid-configuration").toURL();
044        try (InputStream stream = providerConfigurationURL.openStream()) 
045        {
046            // Read all data from URL
047            String providerInfo = IOUtils.toString(stream, StandardCharsets.UTF_8);
048            return OIDCProviderMetadata.parse(providerInfo);
049        }
050    }
051    
052    @Override
053    protected void initUrisScope() throws AccessDeniedException
054    {  
055        Map<String, Object> paramValues = getParameterValues();
056        try
057        {  
058            URI issuerURI = URI.create((String) paramValues.get("authentication.oidc.issuerURI"));
059            OIDCProviderMetadata providerMetadata = _getProviderMetadata(issuerURI);
060            _authUri = providerMetadata.getAuthorizationEndpointURI();
061            _tokenEndpointUri = providerMetadata.getTokenEndpointURI();
062            _iss = providerMetadata.getIssuer();
063            _jwkSetURL = providerMetadata.getJWKSetURI().toURL();
064            _userInfoEndpoint = providerMetadata.getUserInfoEndpointURI();
065            _scope = providerMetadata.getScopes();
066        }
067        catch (Exception e)
068        {
069            getLogger().error("Encountered a problem while retrieving provider metadata", e);
070            throw new AccessDeniedException("Encountered a problem while retrieving provider metadata");
071        }
072    }
073}