package org.fenixedu.bennu.oauth.api; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response.Status; import org.fenixedu.bennu.core.domain.User; import org.fenixedu.bennu.core.rest.BennuRestResource; import org.fenixedu.bennu.oauth.annotation.OAuthEndpoint; import org.fenixedu.bennu.oauth.domain.ApplicationUserAuthorization; import org.fenixedu.bennu.oauth.domain.ApplicationUserSession; import org.fenixedu.bennu.oauth.domain.ExternalApplication; import org.fenixedu.bennu.oauth.domain.ServiceApplication; import org.fenixedu.bennu.oauth.util.OAuthUtils; import pt.ist.fenixframework.Atomic; import com.google.gson.JsonElement; @Path("/oauth") public class OAuthAuthorizationProvider extends BennuRestResource { /*** * Obtains (creating if necessary) oauth tokens for an {@link ExternalApplication} on behalf of a {@link User}. * * It will create an {@link ApplicationUserAuthorization} (if it does not exist yet) as well as the corresponding * {@link ApplicationUserSession}. * * This should be used when a client {@link ServiceApplication} needs to access {@link OAuthEndpoint} endpoints on behalf of * specific {@link User}. Usually this happens in a scenario where both applications (oauth client and oauth server) live * in the same ecosystem. * * @param app the application grant access to * @param username the username of the user to generate tokens to * @return oauth tokens granted for app on behalf of user */ @POST @Path("/provider/{app}/{username}") @OAuthEndpoint(serviceOnly = true, value = "OAUTH_AUTHORIZATION_PROVIDER") @Produces(MediaType.APPLICATION_JSON) public JsonElement getTokens(@PathParam("app") ExternalApplication app, @PathParam("username") String username) { User user = User.findByUsername(username); if (user == null) { throw new WebApplicationException(Status.NOT_FOUND); } return OAuthUtils.getJsonTokens(getOrCreateApplicationUserSession(app, user)); } @Atomic private ApplicationUserSession getOrCreateApplicationUserSession(ExternalApplication app, User user) { ApplicationUserAuthorization applicationUserAuthorization = app.getApplicationUserAuthorization(user).orElseGet(() -> { return new ApplicationUserAuthorization(user, app); }); ApplicationUserSession applicationUserSession = applicationUserAuthorization.getSessionSet().stream().filter(ApplicationUserSession::isAccessTokenValid) .findAny().orElseGet(() -> { final ApplicationUserSession session = new ApplicationUserSession(); session.setApplicationUserAuthorization(applicationUserAuthorization); session.setTokens(OAuthUtils.generateToken(session), OAuthUtils.generateToken(session)); return session; }); return applicationUserSession; } }