001/* 002 * Copyright (c) 2010-2024 Mark Allen, Norbert Bartels. 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining a copy 005 * of this software and associated documentation files (the "Software"), to deal 006 * in the Software without restriction, including without limitation the rights 007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 008 * copies of the Software, and to permit persons to whom the Software is 009 * furnished to do so, subject to the following conditions: 010 * 011 * The above copyright notice and this permission notice shall be included in 012 * all copies or substantial portions of the Software. 013 * 014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 020 * THE SOFTWARE. 021 */ 022package com.restfb; 023 024import com.restfb.exception.FacebookResponseContentException; 025import com.restfb.scope.ScopeBuilder; 026 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.List; 030 031import static com.restfb.util.ObjectUtil.verifyParameterPresence; 032 033/** 034 * InstagramLoginClient is the default implementation of the 035 * <a href="https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login"> 036 * Instagram API with Instagram Login</a>. 037 * <p> 038 * This client is used to use a instagram Login to get a access token, extended access token and so on for the Instagram 039 * API. 040 * <p> 041 * Don't use the client if you are planning to use the Facebbok Login to work with the Instagram API. 042 */ 043public class DefaultInstagramLoginClient extends DefaultFacebookClient { 044 045 public DefaultInstagramLoginClient(Version version) { 046 super(version); 047 } 048 049 public DefaultInstagramLoginClient(String accessToken, Version apiVersion) { 050 super(accessToken, apiVersion); 051 } 052 053 public DefaultInstagramLoginClient(String accessToken, String appSecret, Version apiVersion) { 054 super(accessToken, appSecret, apiVersion); 055 } 056 057 public DefaultInstagramLoginClient(String accessToken, WebRequestor webRequestor, JsonMapper jsonMapper, 058 Version apiVersion) { 059 super(accessToken, webRequestor, jsonMapper, apiVersion); 060 } 061 062 public DefaultInstagramLoginClient(String accessToken, String appSecret, WebRequestor webRequestor, 063 JsonMapper jsonMapper, Version apiVersion) { 064 super(accessToken, appSecret, webRequestor, jsonMapper, apiVersion); 065 } 066 067 @Override 068 public String getLoginDialogUrl(String appId, String redirectUri, ScopeBuilder scope, String state, 069 Parameter... parameters) { 070 List<Parameter> parameterList = new ArrayList<>(); 071 Collections.addAll(parameterList, parameters); 072 parameterList.add(Parameter.with("response_type", CODE)); 073 return getGenericLoginDialogUrl(appId, redirectUri, scope, 074 () -> getFacebookEndpointUrls().getInstagramOAuthEndpoint() + "/oauth/authorize", state, parameterList); 075 } 076 077 @Override 078 public String getLoginDialogUrl(String appId, String redirectUri, ScopeBuilder scope, Parameter... parameters) { 079 return this.getLoginDialogUrl(appId, redirectUri, scope, null, parameters); 080 } 081 082 @Override 083 public AccessToken obtainUserAccessToken(String clientId, String clientSecret, String redirectUri, String code) { 084 verifyParameterPresence(CLIENT_ID, clientId); 085 verifyParameterPresence(PARAM_CLIENT_SECRET, clientSecret); 086 verifyParameterPresence(CODE, code); 087 verifyParameterPresence(REDIRECT_URI, redirectUri); 088 089 return publish(PATH_OAUTH_ACCESS_TOKEN, AccessToken.class, // 090 Parameter.with(CLIENT_ID, clientId), // 091 Parameter.with(PARAM_CLIENT_SECRET, clientSecret), // 092 Parameter.with(CODE, code), // 093 Parameter.with(GRANT_TYPE, "authorization_code"), // 094 Parameter.with(REDIRECT_URI, redirectUri)); 095 } 096 097 @Override 098 public AccessToken obtainExtendedAccessToken(String appId, String appSecret) { 099 verifyParameterPresence(APP_SECRET, appSecret); 100 verifyParameterPresence("accessToken", accessToken); 101 102 String response = makeRequest("access_token", false, false, null, // 103 Parameter.with(PARAM_CLIENT_SECRET, appSecret), // 104 Parameter.with(GRANT_TYPE, "ig_exchange_token"), // 105 Parameter.withFields("access_token,expires_in,token_type")); 106 try { 107 return getAccessTokenFromResponse(response); 108 } catch (Exception t) { 109 throw new FacebookResponseContentException(CANNOT_EXTRACT_ACCESS_TOKEN_MESSAGE, t); 110 } 111 } 112 113 @Override 114 public FacebookClient createClientWithAccessToken(String accessToken) { 115 return new DefaultInstagramLoginClient(accessToken, this.appSecret, getWebRequestor(), getJsonMapper(), 116 this.apiVersion); 117 } 118 119 @Override 120 public AccessToken obtainRefreshedExtendedAccessToken() { 121 String response = makeRequest("refresh_access_token", false, false, null, // 122 Parameter.with(GRANT_TYPE, "ig_refresh_token"), // 123 Parameter.withFields("access_token,expires_in,token_type")); 124 try { 125 return getAccessTokenFromResponse(response); 126 } catch (Exception t) { 127 throw new FacebookResponseContentException(CANNOT_EXTRACT_ACCESS_TOKEN_MESSAGE, t); 128 } 129 } 130 131 @Override 132 protected String createBaseUrlForEndpoint(String apiCall, boolean hasAttachment, boolean hasReel) { 133 if (apiCall.startsWith(PATH_OAUTH_ACCESS_TOKEN)) { 134 return getInstagramApiEndpointUrl(); 135 } 136 return getInstagramGraphEndpointUrl(); 137 } 138 139 private String getInstagramApiEndpointUrl() { 140 return getFacebookEndpointUrls().getInstagramApiEndpoint(); 141 } 142 143 private String getInstagramGraphEndpointUrl() { 144 if (apiVersion.isUrlElementRequired()) { 145 return getFacebookEndpointUrls().getInstagramEndpoint() + '/' + apiVersion.getUrlElement(); 146 } else { 147 return getFacebookEndpointUrls().getInstagramEndpoint(); 148 } 149 } 150}