Invalid OAuth token for user descriptions / image

I’ve been desperate here for days. Searching for everything that come in to my mind, reading many discuss on this side, but i don´t find anything that hepls me.

I was commissioned to build a Discord bot, that sends a message to an discord channel, when someone is starting a live stream. I use Twitch4J for this stuff. But, Twitch4J don`t give me the opportunity, to fetch a channel description and profiel image.

So i tryed to talk to the API directly.

I´ve build an AccesToken generator:

public static TwitchAccesToken getAccesToken() {
	if(accesToken!=null && !accesToken.isExpired()){
		logger.info("Twitch-acces-token | Is valid");
		return accesToken;
	}
		
	logger.warn("Twitch-acces-token | Generating a new token!");
	String url = "https://id.twitch.tv/oauth2/token?";
	HttpResponse<String> response = Unirest.post(url)
			.header("content-type", "application/x-www-form-urlencoded")
			.body("client_id="+clientId+"&client_secret="+clientSecret+"&grant_type=client_credentials")
			.asString();
	String jsonResponse = response.getBody();
	JsonObject json = new Gson().fromJson(jsonResponse, JsonObject.class);
	return new TwitchAccesToken(json);
}

The TwitchAccesToken objekt from the code above.

package de.minetrain.kekbot.discord.features.live_notification.obj;

import com.google.gson.JsonObject;

/**
 * This class represents a Twitch access token, which is used to authorize requests to the Twitch API.
 * @author MineTrain/Justin
 * @since 28.01.2023
 * @version 1.0
 */
public class TwitchAccesToken {
	private final int expiresIn; //The number of milliseconds until the access token expires.
	private final String accessToken; //The actual access token value.
	private final String tokenType; //The token type, which should always "bearer" for Twitch access tokens.

	/**
	* Constructs a new TwitchAccessToken object from a JSON object.
	* @param json The JSON object containing the access token data.
	*/
	public TwitchAccesToken(JsonObject json) {
		this.expiresIn = Integer.parseInt(String.valueOf(json.get("expires_in")));
		this.accessToken = String.valueOf(json.get("access_token"));
		this.tokenType = String.valueOf(json.get("token_type"));
		System.out.println(accessToken+", "+tokenType+", "+expiresIn);
	}

    *** Getter removed ***
	
	/**
	 * Check if the token is expired
	 * @return true if expiresIn < 5 else false
	 */
	public boolean isExpired(){
		return (expiresIn>5) ? false:true;
	}
	
	@Override
	public String toString() {
		return accessToken;
	}
	
}

And then tryed to talk to the API:

HttpResponse<String> response = Unirest.get("https://api.twitch.tv/helix/users")
		.header("Authorization", "Bearer "+TwitchManager.getAccesToken())
		.header("Client-Id", TwitchManager.clientId)
		.queryString("id", channelId)
		.queryString("login", channelName)
		.asString();
					  
String jsonResponse = response.getBody();
JsonObject json = new Gson().fromJson(jsonResponse, JsonObject.class);
System.out.println(json);

But everything i got was this:
{“error”:“Unauthorized”,“status”:401,“message”:“Invalid OAuth token”}

And yes, the acces token is valid, i tryed to log it and it was there:
Token: “exampletoken1234567890”, Type: “bearer”, Exp: 4861876

I´ve heart about the fact, that you need an user access token to access profile images.
But i wonder, how to do this. I have no user Integration, i only need an profile image, based on a twitch channel name, without any user Integration.

Someone an idea how to fix this, or were i can lock for a Solution?

It’s not a language I work with, but from a brief look I don’t see where TwitchManager.getAccesToken() is returning just the token, as it looks like you’re trying to use the whole response from the OAuth process rather than the actual token itself.

No, that’s incorrect. Profile images are public, and you can see by the documentation for that endpoint, https://dev.twitch.tv/docs/api/reference/#get-users, that the only data returned that requires a User token with the appropriate scope would be the email field. If you don’t need the users email address then an App token will work for that endpoint.

1 Like

This is what my http respons thing is based on. I tryed to test things out, for example, when i whirte the “Bearer” in lowercase, it says “No token provided”.

It seems to me, that the call might me correct from my end, but i am very new to API things, outside from library’s, so i don’t now if im right with my assumption.

And,

I´ve build an AccesToken objekt, and overridden the .toString Method, java is using to cast the obj into a string here : .header("Authorization", "Bearer "+TwitchManager.getAccesToken())
I´ve edit the origninal post and add the hole object.

Is there a way i can check if the token that is generatet is actually valid?

You can use the Validate Tokens endpoint https://dev.twitch.tv/docs/authentication/validate-tokens/

1 Like

Okay, my token is acutely invalid.

HttpResponse<String> response = Unirest.get("https://id.twitch.tv/oauth2/validate")
	.header("Authorization", "OAuth "+TwitchManager.getAccesToken())
	.asString();

System.out.println(new Gson().fromJson(response.getBody(), JsonObject.class));

Respond: {"status":401,"message":"invalid access token"}

But, when i create the acces token, my debug says:
"ExampleAccesToken1234567", "bearer", 5153312

Okay i found my problem.

See the " at the start and end from token, and baerer?
The problem was, that was a part from this string. I fixt id :smiley:
Just replace every " with nothing :smiley:

Updatet java object:

package de.minetrain.kekbot.discord.features.live_notification.obj;

import com.google.gson.JsonObject;

/**
 * This class represents a Twitch access token, which is used to authorize requests to the Twitch API.
 * @author MineTrain/Justin
 * @since 29.01.2023
 * @version 1.1
 */
public class TwitchAccesToken {
	private final int expiresIn; //The number of milliseconds until the access token expires.
	private final String accessToken; //The actual access token value.
	private final String tokenType; //The token type, which should always "bearer" for Twitch access tokens.

	/**
	* Constructs a new TwitchAccessToken object from a JSON object.
	* @param json The JSON object containing the access token data.
	*/
	public TwitchAccesToken(JsonObject json) {
		this.expiresIn = Integer.parseInt(String.valueOf(json.get("expires_in")).replace("\"", ""));
		this.accessToken = String.valueOf(json.get("access_token")).replace("\"", "");
		this.tokenType = String.valueOf(json.get("token_type")).replace("\"", "");
		System.out.println(accessToken+", "+tokenType+", "+expiresIn);
	}

	
	/**
	 * Check if the token is expired
	 * @return true if expiresIn < 5 else false
	 */
	public boolean isExpired(){
		return (expiresIn>5) ? false:true;
	}

	/**
	* @return The number of seconds until the access token expires.
	*/
	public int getExpiresIn() {
		return expiresIn;
	}

	/**
	* @return The actual access token value.
	*/
	public String getAccessToken() {
		return accessToken;
	}

	/**
	* @return The token type, which is always "bearer" for Twitch access tokens.
	*/
	public String getTokenType() {
		return tokenType;
	}
	
	@Override
	public String toString() {
		return accessToken;
	}
	
}

Sry for this unnecessary post ;D

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.