I've been trying for a couple of days now to crack this but have not had any success.
I have a web application that I want to use with Google Drives API.
I want the web application to check if there is an access token it can use and if not redirect to Google so the user can log in and grant access.
Seemingly a simple task but it's driving me mad! I've checked the Google documentation but it all seems to be geared around console applications
Google provides an interface UserService which stores details of the users using the application. If the users is not logged in redirect the user to login page using:
response.sendRedirect(userService.createLoginURL(request.getRequestURI()))
Later or if the user is logged in, redirect him to "Request for Permission" page using:
List<String> scopes = Arrays.asList(PlusScopes.PLUS_LOGIN,PlusScopes.PLUS_ME,PlusScopes.USERINFO_EMAIL,PlusScopes.USERINFO_PROFILE......); // Add/remove scopes as per your requirement
List<String> responseTypes = Arrays.asList("code");
GoogleAuthorizationCodeRequestUrl gAuthCode = new GoogleAuthorizationCodeRequestUrl(Google project client id, redirect url, scopes);
gAuthCode.setAccessType("offline");
gAuthCode.setClientId(Google project client id);
gAuthCode.setResponseTypes(responseTypes);
gAuthCode.setApprovalPrompt("force");
authURl = gAuthCode.toURL().toString();
response.sendRedirect(authURl);
Make sure you add all required scopes of the API methods you will be using. After the user has accepted, you will have to create a servlet with "/oauth2callback" mapping to get the authorization code.
request.getParameter("code")
In the same servlet using the code obtained, get refresh and access token making a rest call.
URL url = new URL("https://www.googleapis.com/oauth2/v3/token");
HttpURLConnection connection= (HttpURLConnection)url.openConnection();
connection.setRequestMethod("post");
connection.setDoInput(true);
connection.setDoOutput(true);
DataOutputStream dw= new DataOutputStream(connection.getOutputStream());
dw.writeBytes("code="+authorizationCode+"&client_id="+CLIENT_ID+"&client_secret="+CLIENT_SECRET+"&redirect_uri="+REDIRECT_URL+"&grant_type=authorization_code");
dw.flush();
dw.close();
InputStream inputStream= connection.getInputStream();
Parse the input stream to get your refresh token and access token and redirect the user to your landing page.
Now you have access token to query your api whose scopes were provided in authorization flow. Also you have a refresh token which can be used to regenerate new access token if the previously issued access token has expired.
You should be able to implement the OAuthHandshake using HTTP requests and a redirect URL to your web application. You can play around with the requests here to see what the headers and responses look like: https://developers.google.com/oauthplayground/
You can store the authorization code and tokens any way you like. You would have your web application refer to these tokens to see if they are expired. For example:
def getTokenFromFile(self):
creds = self.readCredsFromDisk()
# check if token is expired
expiration_time = datetime.datetime.strptime(creds['token_expiry'], '"%Y-%m-%dT%H:%M:%S.%f"')
if expiration_time < datetime.datetime.now():
self.refreshToken()
# reload creds
creds = self.readCredsFromDisk()
return creds['access_token']
I'm writing just a python script that does the handshake and saves the token to a plain text file. Any time the script runs a function to the Google API it will use this function.
The refresh function:
def refreshToken(self):
with open('client_secret.json') as s:
secret = json.load(s)
secret = secret['installed']
creds = self.readCredsFromDisk()
refresh_url = secret['token_uri']
post_data = {'client_id':secret['client_id'],
'client_secret':secret['client_secret'],
'refresh_token':creds['refresh_token'],
'grant_type':'refresh_token'}
headers = {'Content-type':'application/x-www-form-urlencoded'}
(resp, content) = self.http.request(refresh_url,
method='POST',
body=urlencode(post_data),
headers=headers)
content = json.loads(content)
creds['access_token'] = content['access_token']
date = datetime.datetime.now() + datetime.timedelta(seconds=content['expires_in'])
creds['token_expiry'] = json.dumps(date.isoformat())
self.writeCredsToDisk(json.dumps(creds))
You would write a function similar to this to trade the original authorization code and access code following the logic the OAuth Playground shows you.
Related
So I'm trying to import Cardano Blockchain data like address balance, amount staked, rewards etc into a Google Sheet. I found this project named Blockfrost.io which is an API for accessing Cardano blockchain info and import it into apps etc.
I think I can use this with Google Sheets. Problem is I don't know how to authenticate. I've searched all around on the documentation and it's not clear to me. It seems it's possible if your're building an app or using the terminal.
But I just want to authenticate in the easiest way possible like in the browser address bar that way it would be simple to get the JSON with the info I need and import the info to Google Sheets.
This is where it mentions the Authentication:
https://docs.blockfrost.io/#section/Authentication
I already have an API key to access. But how do I authenticate?
So if I want to check the blockchain metrics (mainnet1234567890 is a dummy key, I won't use mine here):
https://cardano-mainnet.blockfrost.io/api/v0/metrics/project_id:mainnet1234567890
The JSON will still output this:
status_code 403
error "Forbidden"
message "Missing project token. Please include project_id in your request."
Is there a correct way to authenticate on the browser address bar?
It's not clear which BlockFrost API you are using Go JavaScript etc...
the API key goes in as a header on the request object. I was manually trying to connect to the service and found for a request is what I had to do in C#...
var aWR = System.Net.WebRequest.Create(url);
aWR.Method = "GET";
aWR.Headers.Add("project_id", "mainnetTheRestOfMyKeyIsHidden");
var webResponse = aWR.GetResponse();
var webStream = webResponse.GetResponseStream();
var reader = new StreamReader(webStream);
var data = reader.ReadToEnd();
Later I realized I wanted to use their API cause they implement the rate limiter, something I would rather use than build... I use the following with the BlockFrost API in c#
const string apiKey = "mainnetPutYourKeyHere";
const string network = "mainnet";
// your key is set during the construction of the provider.
ServiceProvider provider = new ServiceCollection().AddBlockfrost(network, apiKey).BuildServiceProvider();
// from there individual services are created
var AddressService = provider.GetRequiredService<IAddressesService>();
// The call to get the data looked like
AddressTransactionsContentResponseCollection TXR = await AddressService.GetTransactionsAsync(sAddress, sHeightFrom, sHeightTo, 100, iAddressPage, ESortOrder.Desc, new System.Threading.CancellationToken());
// etc. your gonna need to set the bounds above in terms of block height
Try using postman and include the "project_id" header with api key as the value like this - it will clear up the concept for you I think:enter image description here
I cannot understand how this works:
from flask import Flask, redirect
oauth_uri = 'https://accounts.freelancer.com/oauth/authorise'
client_id = '<CLIENT_ID>'
redirect_uri = '<CLIENT_REDIRECT_URI>'
prompt = 'select_account consent'
advanced_scopes = '1 3'
app = Flask(__name__)
# Users who hit this endpoint will be redirected to the authorisation prompt
#app.route('/authorize')
def handle_authorize():
return redirect(
'{0}?response_type=code'
'&client_id={1}&redirect_uri={2}'
'&scope=basic&prompt={3}'
'&advanced_scopes={4}'.format(
oauth_uri, client_id, redirect_uri, prompt, advanced_scopes
)
)
This code gives me : Invalid redirect URI in browser.
Whats this redirect URI, why can't I give any redirect uri of my choice?
Its documented here: can anyone please explain to me how this works,
https://developers.freelancer.com/docs/authentication/generating-access-tokens#header-receive-authorisation-response
The redirect URL is the URL you set for your application on your apps dashboard. You need to specify a valid URL for Freelancer.com to redirect to after the user has granted access for your app. Think of how Facebook grants access to third party apps using their log in system.
I have created an application in Box and got an API Key, and then edited the redirect URL. But when I accessed through URL https://www.box.net/api/1.0/rest?action=get_ticket&api_key=APIKEY, I'm not getting a positive response, instead of I'm getting a response like:
<response>
<status>application_restricted</status>
</response>
Please provide me a solution to get access to the application.
Thanks in advance.
The V1 API has been deprecated and will no longer provide authentication or file access. You need to migrate your application to the V2 API, which is documented here.
For accessing access_token using java sdk , You need to have following key values
1) clienId > Use Application console
2) client_secret > Use application console
3) code > Code value you will get using below link
https://account.box.com/api/oauth2/authorize?response_type=code&client_id={your_client_id}&state=security_token%3DKnhMJatFipTAnM0nHlZA
Replace your client id with original value. client id you will get from your apps.
And Follow steps and authorize you application using your credential.
after that it will redirect to https://localhost/?state=security_token%3DKnhMJatFipTAnM0nHlZA&code=sdsdsd3sdsdC0oGqOS2WgaFipZBdj
Copy code value
String clienId = "your client id ";
String client_secret = "your secret id";
String code = "sdsdsd3sdsdC0oGqOS2WgaFipZBdj"; // use above extracted code value
BoxAPIConnection con = new BoxAPIConnection(clienId,client_secret,code);
String accessToken = con.getAccessToken();
System.out.println("Accss_Token : " +accessToken);
I am using Box Api v2 (java) for integrating my webapp with Box.com.
I forward the user to the authorize url
https://www.box.com/api/oauth2/authorize?response_type=code&client_id=client-id
..and receive the 'code' at my redirect end-point. Using this code, I am able to get the access_token and refresh_token. I know that access_token is valid only for 1 hr.
But can I re-use the access_token within this 3600 sec period?
eg:a user comes back within 30 minutes and tries to fetch/put files
In this scenario, I will need to create a new BoxClient.
So what is the recommended method of client authentication using the existing access token?
If answerer can paste code snippets using the box java api, it would be quite helpful.
Or is the refreshing to get new access_token and refresh_token, the only method available?
BoxClient client = new BoxClient(MY_CLIENT_ID, MY_CLIENT_SECRET);BoxOAuthManager mgr = client.getOAuthManager();
// This is refresh
BoxOAuthRequestObject requestObject = BoxOAuthRequestObject.refreshOAuthRequestObject(REFRESH_TOKEN, MY_CLIENT_ID, MY_CLIENT_SECRET);
BoxOAuthToken newToken = mgr.refreshOAuth(requestObject);
client.authenticate(newToken);
Yes, you can re-use the access token within the 3600-second period. A common pattern for web applications is to store the access_token and refresh_token (and optionally their expiration datetimes) in a database record associated with the user.
what is the recommended method of client authentication using the existing access token?
You'll use the same authentication method as when you first acquired the access token. You don't have to do anything special to reuse it. If the access_token is expired, as determined by either an expiration timestamp comparison or 401 response, you can use the refresh_token to get a new token pair. By refreshing and persisting the token pair in this manner you can keep the user authenticated indefinitely.
BoxOAuthToken accessToken = new BoxOAuthToken(Map) will work here.
// where Map contains
{
"exprires_in":"3600",
"token_type":"bearer",
"refresh_token":"<refresh_token>",
"access_token":"<access_token>"
}
Map authMap;
BoxOAuthToken accessToken = new BoxOAuthToken(authMap);
client.authenticate(newToken);
after reading the oauth documentation on box's website, I understand the steps to get access_token and refresh_token, which requires authorization_code.
step1: send Get request to https://www.box.com/api/oauth2/authorize?response_type=code&client_id=CLIENT_ID&state=authenticated&redirect_uri=https://www.appfoo.com
step2: after entering credentials of box in browser and then click the "Allow" button, redirect to the specified redirect_uri with state=authenticated&code=AUTHORIZATION_CODE
step3: now with the AUTHORIZATION_CODE in the redirect url from step2, getting access_token can be done programmatically, by sending POST request to https://www.box.com/api/oauth2/token with AUTHORIZATION_CODE, client_id, client_secret in body and then parsing the returned json response.
My question is: is it possible to programmatically do step1 and step2 instead of via browser?
thank you very much!
The current OAuth 2 flow requires the user to go through the browser and can't be done programmatically.
It is possible, just imitate every form with cURL and on second step post cookies.
First time you will need 3 requests, next time only one (if refresh_token isn't expired, otherwise 3 again)
The point about imitating the browser transactions is a good one but instead of using cURL you would want to use a higher level tool like mechanize (available for ruby, perl and python). It will handle the cookies for you and can programatically traverse forms and links. Good for page scraping and writing scripts to order hot concert tickets from TicketMaster too!
If you have the authorization code, you then should be able to get the OAuth Token(access_token, refresh_token) via SDK, correct?
In response to aIKid, this is what I first do to get a BoxClient
BoxClient client = new BoxClient(clientId, clientSecret);
Map<String,Object> authToken = new HashMap<String,Object>();
authToken.put("exprires_in","3600");
authToken.put( "token_type","bearer");
authToken.put("refresh_token", clientRefreshToken);
authToken.put("access_token",clientAccessToken);
BoxOAuthToken oauthToken = new BoxOAuthToken(authToken);
client.authenticate(oauthToken);
return client;
Then, I have this to create a new user,
BoxUser createdUser = new BoxUser();
BoxUserRequestObject createUserRequest = BoxUserRequestObject.createEnterpriseUserRequestObject("someEmail.domain.com", "test user");
createdUser = client.getUsersManager().createEnterpriseUser(createUserRequest);
Now I'm trying to figure out how to do the RUD part of my CRUD operations on users and groups.