invalid token index when issuing token - code-snippets

After deploy a NFT smart contract on Elrond Blockchain, I'm trying to issueToken using snippets:
erdpy --verbose contract call ${ADDRESS} --recall-nonce --pem=${ALICE} --gas-limit=${GAS_LIMIT} \
--function="issueToken" \
--value ${MINT_COST} \
--arguments ${ISSUE_TOKEN_ARGUMENTS} \
--proxy=${PROXY} --chain=${CHAINID} --send \
--outfile="${MY_LOGS}/issueToken.json"
}
but I get the error "invalid token index"

Since the token issue is managed by the smart contract you're calling (because you are calling the issueToken endpoint of that contract), the most likely cause is that you're not passing the correct parameters to the issueToken endpoint.
You have to know first what parameters does your contract expect for that endpoint, then pass them hex encoded according to the expected format.
For your specific case, if the endpoint signature looks like this:
#[only_owner]
#[payable("EGLD")]
#[endpoint(issueToken)]
fn issue_token(
&self,
#[payment] issue_cost: BigUint,
token_name: ManagedBuffer,
token_ticker: ManagedBuffer,
) -> SCResult<AsyncCall>
then the $ISSUE_TOKEN_ARGUMENTS should contain something like this:
ISSUE_TOKEN_ARGUMENTS="str:MyTokenName str:MYTKNTICKER"

Here is the issueToken endpoint
#[only_owner]
#[payable("EGLD")]
#[endpoint(issueToken)]
fn issue_token(
&self,
#[payment] issue_cost: BigUint,
token_name: ManagedBuffer,
token_ticker: ManagedBuffer,
) -> SCResult<AsyncCall> {
require!(self.nft_token_id().is_empty(), "Token already issued");
Ok(self
.send()
.esdt_system_sc_proxy()
.issue_non_fungible(
issue_cost,
&token_name,
&token_ticker,
NonFungibleTokenProperties {
can_freeze: true,
can_wipe: true,
can_pause: true,
can_change_owner: false,
can_upgrade: false,
can_add_special_roles: true,
},
)
.async_call()
.with_callback(self.callbacks().issue_callback()))
}

Related

rust - Why am I getting an invalid request error using twitter api

So over at the twitter api documentation, it says to generate a Bearer token you run this command
curl --user "$API_KEY:$API_SECRET_KEY" \
--data 'grant_type=client_credentials' \
'https://api.twitter.com/oauth2/token'
I run it and the result I get is the HTML for https://api.twitter.com/ouath2/token
Then I wrote some rust code,
extern crate reqwest;
use reqwest::{ Client };
// Twitter api endpoint - https://api.twitter.com/
#[tokio::main]
async fn main() -> Result<(), reqwest::Error>{
let http_client =Client::new();
// We need to get a bearer_token before we can access anything with the twitter api
let bearer_token = http_client.post("https://api.twitter.com/oauth2/token")
.basic_auth(API_KEY, Some(API_KEY_SECRET)
.body("grant_type=client_credentials")
.send().await?
.text().await?;
println!("{}", bearer_token);
Ok(())
}
After executing the rust code above, this is what is printed,
{"errors":[{"code":170,"message":"Missing required parameter: grant_type","label":"forbidden_missing_parameter"}]}
However from the documentation the expected result is this:
{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAMLheAAAAAAA0%2BuSeid%2BULvsea4JtiGRiSDSJSI%3DEUifiRBkKG5E2XzMDjRfl76ZC9Ub0wnz4XsNiRVBChTYbJcE3F"}
Does anyone know why?
Here's my cargo.toml file
[package]
name = "release"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
By the way, I applied for twitter developer access a few hours back, but I'm not sure on how to check if I do have access. I mean, I can make a project, and an app and access the dashboard.
https://api.twitter.com/2/oauth2/token is the wrong URI, it should be https://api.twitter.com/oauth2/token
Are there any brackets missing?
.basic_auth(API_KEY, Some(API_KEY_SECRET)
.basic_auth(API_KEY, Some(API_KEY_SECRET))

How to reuse Jenkins credentials without masking the PASSWORD in withCredentials.usernamePassword?

Background
I'm using scripted pipelines and Shared Libraries.
All the implementation we have is under the src directory where I reuse the reference in pipelines:
def static myFunction(steps, context) {
steps.withCredentials([steps.usernamePassword(
credentialsId: 'credentialsId',
usernameVariable: 'GITHUB_USERNAME',
passwordVariable: 'GITHUB_PASSWORD')]) {
// use of steps.env.GITHUB_PASSWORD
}
}
I need to make 2 API calls to Github Enterprise with the same Credentials, which is set as the UsernamePassword credentials
Although the first call works as expected, the second call fails because of the env.GITHUB_PASSWORD value is masked
Details
As described in https://wiki.jenkins.io/display/JENKINS/Credentials+Binding+Plugin, the problem might be related to how the Credentials binding is masked when used more than once. That is, once we use ${env.PASSWORD} once, it will mask all the uses of the same value.
Detail
I'm using curl to and I need to generate the URL
def teamMembersApi = sh(curl -H 'Authorization: token ${env.PASSWORD}' ${githubRepoApi}")
The response of this call is another API URL, which I created another URL with the "teamMembersApi". So, making the second call...
def teamMembers = sh("curl -H 'Authorization: token ${env.PASSWORD}' ${teamMembersApi}")
At this point, the value of ${env.PASSWORD} is masked and, as a consequence, the second call fails because of invalid credentials
Questions
As I understand, this is a result of the "masking" of values when accessed via any method that will cause a "toString()" will make it not available for reuse in Strings...
How can I reuse the same credentials, even when they are eligible to be masked?
Verifications
I tried using 2 blocks of steps.withCredentials
I tried using the httpRequest step to not refer to variable
Using httpRequest, I got MalformedURLException with a clearly well-formed URL... I made sure the URL was in String format and has the protocol...
java.net.MalformedURLException: no protocol: https://github.company.com/org/repo
You can use the username/password inside withCredentials block for any times. But
keep in mind, the username/password can only survive inside withCredentials block.
I used the same username/password for twice in following code and it worked well.
node('docker') {
withCredentials([steps.usernamePassword(
credentialsId: 'ba2e4f46-56f1-4467-ae97-17b356d7f854',
usernameVariable: 'JENKINS_USERNAME',
passwordVariable: 'JENKINS_PASSWORD')]) {
def log = sh(
returnStdout: true,
script: "curl -u ${env.JENKINS_USERNAME}:${env.JENKINS_PASSWORD} -k ${env.BUILD_URL}" + 'consoleText').trim()
def pipelineSteps = sh(
returnStdout: true,
script: "curl -u ${env.JENKINS_USERNAME}:${env.JENKINS_PASSWORD} -k ${env.BUILD_URL}" + 'flowGraphTable').trim()
echo '\n## build log ##\n' + log
echo '\n## pipelineSteps ##\n' + pipelineSteps
}
echo "JENKINS_USERNAME: ${env.JENKINS_USERNAME}"
// print JENKINS_USERNAME: null
// because JENKINS_USERNAME's lifecycle is limited inside withCredentials blok.
}
Another issue in your code, if you did not specify option returnStdout: true for step sh, it should return null. Example: def output = sh('command'), output will be null

Access Google spreadsheet API without auth token

I have created Google Spreadsheet, and given edit access to all (can edit even without login).
Here is the link. I would like to update this sheet with Google Spreadsheet API. But I am getting error. My requirement is update the sheet thru API even without access credential.
It is possible to write to spreadsheet without OAuth or API Keys. You need to use Service Account Keys.
Here is what I did for my Node.js environment.
Get a service account key from https://console.cloud.google.com/apis/credentials (You can here also restrict what this keys is allowed todo)
When creating, make sure you click the Furnish a new private key
Select JSON when it asks you how to download the key.
The service account key you have just generated includes a client_email.
Go to you google spreadsheet and allow this client_email to have write access on this document
Use the following code to authenticate
let jwtClient = new google.auth.JWT(client_email, null, private_key, [
"https://www.googleapis.com/auth/spreadsheets",
]);
//authenticate request
jwtClient.authorize(function(err, tokens) {
// at this point the authentication is done you can now use `jwtClient`
// to read or write to the spreadsheet
});
client_email and private_key are part of the service account key
A more detailed description can be found here. http://isd-soft.com/tech_blog/accessing-google-apis-using-service-account-node-js/ Also, all credit goes to this page.
You need to be authorized to make such requests
Every request your application sends to the Google Sheets API needs to
identify your application to Google. There are two ways to identify
your application: using an OAuth 2.0 token (which also authorizes the
request) and/or using the application's API key. Here's how to
determine which of those options to use:
If the request requires authorization (such as a request for an
individual's private data), then the application must provide an OAuth
2.0 token with the request. The application may also provide the API key, but it doesn't have to. If the request doesn't require
authorization (such as a request for public data), then the
application must provide either the API key or an OAuth 2.0 token, or
both—whatever option is most convenient for you.
That's it. There's no bypassing authorization.
Finally digged deep enough and found the answer. Any kind of writing, even to publicly editable sheets requires an OAuth flow:
https://issuetracker.google.com/issues/36755576#comment3
Jürgen Brandstetter's answer above is completely right. Using Postman, I have been successful without using an OAuth token (I needed my personal API key and a service account) - I have written to a new sheet (in fact I did a batchUpdate operation with two steps, first create a new sheet and then pasteData on it). I followed the instructions here to create a service account, downloaded the credentials JSON and used it to create and sign a JWT string that is later used as Bearer.
Here is the Java code to obtain the JWT string:
private static String getSignedJWT() throws IOException {
InputStream in = YourClass.class.getResourceAsStream("/downloaded-service-account-creds.json");
if (in == null) {
throw new FileNotFoundException("Resource not found");
}
ServiceAccountCredentials serviceAccountCredentials = ServiceAccountCredentials.fromStream(in);
GoogleCredentials googleCredentials = serviceAccountCredentials
.createScoped(Collections.singletonList(SheetsScopes.SPREADSHEETS));
PrivateKey privateKey = serviceAccountCredentials.getPrivateKey();
String privateKeyId = serviceAccountCredentials.getPrivateKeyId();
long now = System.currentTimeMillis();
Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey)privateKey);
String signedJwt = JWT.create()
.withKeyId(privateKeyId)
.withIssuer(serviceAccountCredentials.getClientEmail())
.withSubject(serviceAccountCredentials.getClientEmail())
.withAudience("https://sheets.googleapis.com/")
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + 3600 * 1000L))
.sign(algorithm);
return signedJwt;
}
Dependencies needed: com.auth0:java-jwt and com.google.auth:google-auth-library-oauth2-http.
Here's the curl that uses the JWT string generated above:
curl --location --request POST 'https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID:batchUpdate?key=ANY_PERSONAL_API_KEY' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_STRING' \
--data-raw '{
"requests": [
{
"addSheet": {
"properties": {
"title": "newPred",
"sheetId": 0
}
}
},
{
"pasteData": {
"coordinate": {
"columnIndex": 0,
"rowIndex": 0,
"sheetId": 0
},
"delimiter": "\t",
"data": "col1\tcol2\nPeter\t25",
"type": "PASTE_NORMAL"
}
}
]
}'
Not exactly what asked but here is a solution with google-api-nodejs-client worked for me:
const { google } = require('googleapis');
const sheets = google.sheets('v4');
const spreadsheetId = '.........';
(async () => {
const auth = new google.auth.GoogleAuth({
keyFile: './my_service_account_privatekey.json',
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
// get
try {
const getResult = await sheets.spreadsheets.values.get({
auth,
spreadsheetId,
range: 'Sheet1!B2:C4'
})
console.log('Got values:', getResult.data.values)
} catch (error) {
console.error('Get error:', error)
}
})()
docs: https://github.com/googleapis/google-api-nodejs-client#using-the-keyfile-property

How to get a full list of repositories that a user is allowed to access?

I have found bitbucket api like:
https://bitbucket.org/api/2.0/repositories/{teamname}
But this link return 301 status (moved permanently to !api/2.0/repositories/{teamname}).
Ok, but this one returns status 200 with zero repositories.
I provide two parameters as user and password, but nothing seems changed.
So, can anybody answer how to get full list of private repositories that allowed to specific user?
Atlassian Documentation - Repositories Endpoint provides a detail documentation on how to access the repositories.
The URL mentioned in bitbucket to GET a list of repositories for an account is:
GET https://api.bitbucket.org/2.0/repositories/{owner}
If you use the above URL it always retrieves the repositories where you are the owner. In order to retrieve full list of repositories that the user is member of, you should call:
GET https://api.bitbucket.org/2.0/repositories?role=member
You can apply following set of filters for role based on your needs.
To limit the set of returned repositories, apply the
role=[owner|admin|contributor|member] parameter where the roles are:
owner: returns all repositories owned by the current user.
admin: returns repositories to which the user has explicit
administrator access.
contributor: returns repositories to which the user has explicit write access.
member: returns repositories to which the user has explicit read
access.
Edit-1:
You can make use of Bitbucket REST browser for testing the request/response.(discontinued)
You should not use the API from the https://bitbucket.org/api domain.
Instead, you should always use https://api.bitbucket.org.
Now one reason you might be getting an empty result after following the redirect could be because some http clients will only send Basic Auth credentials if the server explicitly asks for them by returning a 401 response with the WWW-Authenticate response header.
The repositories endpoint does not require authentication. It will simply return the repos that are visible to anonymous users (which might well be an empty set in your case) and so clients that insist on a WWW-Authenticate challenge (there are many, including Microsoft Powershell) will not work as expected (note, curl always sends Basic Auth credentials eagerly, which makes it a good tool for testing).
Unfortunately, from what I see in the documentation, there is no way to list all private repositories which the user has access to.
GET https://api.bitbucket.org/2.0/repositories
"Returns a paginated list of all public repositories." according to the doco.
GET https://api.bitbucket.org/2.0/repositories/{owner}
"Returns a paginated list of all repositories owned by the specified account or UUID." according to the doco.
So, getting all private repositories not necessarily owned by the user is either not possible, or I haven't found the right endpoint, or the documentation is inacurate.
None of the answers above worked for me, so this is what I did. We'll use the Bitbucket REST API.
Authentication
You can't use your normal credentials. I created an API Password. I'm not sure how to get to this page via your browser, but go here: https://bitbucket.org/account/settings/app-passwords/
Create an App Password, then cut and save the password that Atlassian generates for you.
Curl
curl --user your_username:your_app_password https://api.bitbucket.org/2.0/repositories/your_workspace?pagelen=100
I piped that to jq and saved it to a file.
your_workspace you get from looking at the URL of any of your repositories.
Paging
The maximum pagelen appears to be 100. If you have more than 100 repos, then you might have to do this:
curl --user your_username:your_app_password https://api.bitbucket.org/2.0/repositories/your_workspace?pagelen=100&page=2
The JSON
The JSON isn't too bad. You want the "values" array. From there, look at links.clone, which might have two entries like this:
"clone": [
{
"href": "https://user#bitbucket.org/WORKSPACE/REPO.git",
"name": "https"
},
{
"href": "git#bitbucket.org:WORKSPACE/REPO.git",
"name": "ssh"
}
],
That's a cut & paste from my results with personal info changed. Also useful are two other fields:
"full_name": "WORKSPACE/repo",
"name": "Repo",
Expanding on blizzard's answer, here's a little node.js script I just wrote:
import axios from 'axios';
import fs from 'fs';
async function main() {
const bitbucket = axios.create({
baseURL: 'https://api.bitbucket.org/2.0',
auth: {
username: process.env.BITBUCKET_USERNAME!,
password: process.env.BITBUCKET_PASSWORD!,
}
});
const repos = [];
let next = 'repositories?role=member';
for(;;) {
console.log(`Fetching ${next}`)
const res = await bitbucket.get(next);
if(res.status < 200 || res.status >= 300) {
console.error(res);
return 1;
}
repos.push(...res.data.values);
if(!res.data.next) break;
next = res.data.next;
}
console.log(`Done; writing file`);
await fs.promises.writeFile(`${__dirname}/../data/repos.json`,JSON.stringify(repos,null,2),{encoding:'utf8'});
}
main().catch(err => {
console.error(err);
});

Valid Google OAuth2 token unparseable?

I've got a valid OAuth2 token that Google accepts, but GoogleIdTokenVerifier cannot even parse it.
The token is ya29.1.AADtN_XcjzHgauKetBvrbgHImGFg1pjiHRQAKHyTglBDjEZsTPUMQJ5p-xAKtk955_4r6MdnTe3HZ08 (no worries, it's already expired).
It's obtained on Android using
accountManager.blockingGetAuthToken(account, "oauth2:https://www.googleapis.com/auth/userinfo.email", true);
When I call https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=...
I get sane result like
{
"issued_to": "34951113407.apps.googleusercontent.com",
"audience": "34951113407.apps.googleusercontent.com",
"scope": "https://www.googleapis.com/auth/userinfo.email",
"expires_in": 3175,
"email": "me#gmail.com",
"verified_email": true,
"access_type": "offline"
}
So it must be a valid token.
But when I call
new GoogleIdTokenVerifier(new UrlFetchTransport(), JacksonFactory.getDefaultInstance())
.verify(authToken)
It gives me
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('É' (code 201)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.ByteArrayInputStream#69886979; line: 1, column: 2]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1378)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:599)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:520)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2275)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:788)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:674)
at com.google.api.client.json.jackson2.JacksonParser.nextToken(JacksonParser.java:55)
at com.google.api.client.json.JsonParser.startParsing(JsonParser.java:213)
at com.google.api.client.json.JsonParser.parse(JsonParser.java:372)
at com.google.api.client.json.JsonParser.parse(JsonParser.java:328)
at com.google.api.client.json.JsonParser.parseAndClose(JsonParser.java:158)
at com.google.api.client.json.JsonParser.parseAndClose(JsonParser.java:140)
at com.google.api.client.json.JsonFactory.fromInputStream(JsonFactory.java:206)
at com.google.api.client.json.webtoken.JsonWebSignature$Parser.parse(JsonWebSignature.java:480)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.parse(GoogleIdToken.java:57)
at com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.verify(GoogleIdTokenVerifier.java:190)
By debugging JsonWebSignature it seems that token payload is just 1.
Android 4.4.2
com.google.http-client:google-http-client-jackson2:1.17.0-rc
com.fasterxml.jackson.core:jackson-core:2.3.0 (also tried included 2.1.3 from transient dependencies of google-http-client-jackson)
Also tried GsonFactory, exception is different, but also clearly cannot be parsed by JsonWebSignature.parse().
What I did wrong? Are there different tokens formats out there?
There are indeed different token formats out there.
The OAuth2 token you have there is the access_token -- it says that your software is authorized with the scope you requested, but it doesn't say anything about which user is actually making the request.
There is another type of token which the GoogleIdTokenVerifier expects to verify: an OpenID Connect id_token. A lot of services use that one, because it means some third party is authenticating that the traffic you're looking at came from that human (more or less!).
There's a little more background here, but the short version is that you should consider using GoogleAuthUtil#getToken(Context, String, String) -- it will return the id_token as a String -- or else consider exactly which scopes you need, and consider requesting the openid scope instead of the current oauth2:https://www.googleapis.com/auth/userinfo.email.
I know this answer is probably too late to help you :)

Resources