001/*
002 *  Copyright 2023 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.oauth;
017
018import java.io.IOException;
019import java.net.URI;
020import java.util.Optional;
021import java.util.Set;
022
023import org.apache.cocoon.ProcessingException;
024import org.apache.cocoon.environment.Redirector;
025
026import org.ametys.runtime.authentication.AccessDeniedException;
027
028import com.nimbusds.oauth2.sdk.AuthorizationGrant;
029import com.nimbusds.oauth2.sdk.Scope;
030import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
031import com.nimbusds.oauth2.sdk.id.ClientID;
032import com.nimbusds.oauth2.sdk.id.State;
033import com.nimbusds.oauth2.sdk.token.AccessToken;
034
035/**
036 * Represent an OAuth authorization server
037 */
038public interface OAuthProvider
039{
040    /**
041     * Get the extension id
042     * @return the id
043     */
044    public String getId();
045    
046    /**
047     * Get the client id provided by the authorization server.
048     * @return the client id
049     */
050    public ClientID getClientID();
051    
052    /**
053     * Get the client authentication to use for new token request
054     * @return the authentication
055     */
056    public ClientAuthentication getClientAuthentication();
057    
058    /**
059     * Get the authorization endpoint for the provider
060     * @return the uri
061     */
062    public URI getAuthorizationEndpointURI();
063    
064    /**
065     * Get the token endpoint for the provider
066     * @return the uri
067     */
068    public URI getTokenEndpointURI();
069
070    /**
071     * Get the list of custom parameters returned with the access token.
072     * The listed parameters are stored with the access token for later
073     * use.
074     * @return the list of parameter names
075     */
076    public Set<String> getCustomParametersName();
077    
078    /**
079     * Get the scope to request to the provider.
080     * {@code null} if no scope should be use.
081     * @return the scope or {@code null}
082     */
083    public Scope getScope();
084    
085    /**
086     * Get the stored access token if it exist.
087     * 
088     * If a token exists, but is expired, this method will silently try to refresh it.
089     * @return the access token or empty
090     */
091    public Optional<AccessToken> getStoredAccessToken();
092    
093    /**
094     * Try to get the currently stored access token for the given provider.
095     * If no valid token is available, the method should return {@link Optional#empty()}
096     * and try to redirect to the authorization protocol.
097     * 
098     * @see #getStoredAccessToken() if you don't want to redirect
099     * 
100     * @param redirector the redirector to use if no token are available.
101     * @return the token or {@link Optional#empty()}
102     * @throws ProcessingException if an error occurred while redirecting
103     * @throws IOException if an error occurred while redirecting
104     */
105    public Optional<AccessToken> getAccessToken(Redirector redirector) throws ProcessingException, IOException;
106    
107    /**
108     * Indicate that the provider is expecting an authorization response
109     * for the provided state.
110     * 
111     * @param state the state
112     * @return true if the provider has initiated a authorization process with this state and the process is not complete yet.
113     */
114    public boolean isKnownState(State state);
115
116    /**
117     * Retrieve the stored value for a custom parameter
118     * @param <T> the type of the value to retrieve. This must be a valid JSON type
119     * @param parameter the name of the parameter
120     * @return the value of the parameter if it exists
121     */
122    public <T> Optional<T> getStoredCustomParameter(String parameter);
123
124    /**
125     * Request a token to an authorization server using an authorization
126     * code previously provided by the authorization server.
127     * 
128     * This method will store the result of the token request in session.
129     * See {@link #getStoredAccessToken()} and {@link #getAccessToken(Redirector)}
130     *  for how to use the requested token.
131     * 
132     * @param authorizationGrant the grant to use to request the token
133     * @return the new access token
134     * @throws IOException if an error occurred while communicating with the token endpoint
135     * @throws AccessDeniedException if the response contains error
136     * 
137     * @see #getStoredAccessToken()
138     * @see #getAccessToken(Redirector)
139     */
140    public AccessToken requestAccessToken(AuthorizationGrant authorizationGrant) throws IOException;
141}