I'm trying to make a Slack App, using Bolt library.
I made a simple Hello World application according to official docs: https://api.slack.com/start/building/bolt-java
Credentials I inject from properties file, that's what my SlackApp class lookalike:
#Configuration
public class SlackApp {
private final String secret;
private final String token;
public SlackApp(#Value("${slack.signing-secret}") String secret,
#Value("${slack.bot-token}") String token) {
this.secret = secret;
this.token = token;
}
#Bean
public App initSlackApp() {
AppConfig config = AppConfig.builder()
.signingSecret(secret)
.singleTeamBotToken(token)
.build();
App app = new App(config);
app.command("/hello", (req, ctx) -> {
return ctx.ack("What's up?");
});
return app;
}
}
Token and secret, I've obtained like in this part of docs: https://slack.dev/java-slack-sdk/guides/getting-started-with-bolt
But when I try to turn on Event Subscription in Slack API I got Your URL didn't respond with the value of the challenge parameter. error.
And in application logs I've got
2021-11-30 17:27:08.364 DEBUG 81561 --- [nio-3000-exec-4] c.s.a.a.SlackSignature$Verifier : Request verification (timestamp: 1638278828, body: {"token":"VERIFICATION_TOKEN","challenge":"CHALLENGE","type":"url_verification"}, signature: v0=SIGNATURE)
2021-11-30 17:27:08.366 INFO 81561 --- [nio-3000-exec-4] c.s.a.b.m.builtin.RequestVerification : Invalid signature detected - v0=SIGNATURE
What can be reason of invalid signature error, if both signing secret and bot token is correct?
Related
When I try to verify the Firebase jwt token in my Spring Boot backend application, I get the following error:
Failed to verify the signature of Firebase ID token. See
https://firebase.google.com/docs/auth/admin/verify-id-tokens for
details on how to retrieve an ID token.
In the client (Flutter) I log the jwt as follows:
GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
UserCredential authResult = await _auth.signInWithCredential(credential);
_user = authResult.user;
logger.i(await _user.getIdToken()); // Print jwt
I send the jwt that gets logged to my backend through the Authorization header as a bearer token.
Using Spring security (it doesn't matter), I just perform the following check:
FirebaseToken decoded = FirebaseAuth.getInstance().verifyIdToken(token);
My firebase app init config is pretty standard (env variable pointing to config.json is set):
#Primary
#Bean
public void firebaseInit() throws IOException {
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.getApplicationDefault())
.build();
if (FirebaseApp.getApps().isEmpty()) {
FirebaseApp.initializeApp(options);
}
}
After debugging, following method throws in class RSASignature (package package sun.security.rsa):
#Override
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
if (publicKey == null) {
throw new SignatureException("Missing public key");
}
try {
if (sigBytes.length != RSACore.getByteLength(publicKey)) {
throw new SignatureException("Signature length not correct: got " +
sigBytes.length + " but was expecting " +
RSACore.getByteLength(publicKey));
}
sigBytes length is 113, whereas it expects to be 256.
Perhaps I'm doing something wrong though...
My God... the logger that I used in dart decided to just cap the jwt string so the jwt was incomplete.
Now I get a message 'forbidden' happy joy. But the previous error has been resolved.
Edit 'Forbidden' was consequence of a minor Spring Boot issue (adding roles to authorities).
It now works as expected.
I'm building a 3rd party app to authenticate with Contact Center Express. The documentation is necessary, but insufficient to accomplish this. For example,
https://developer.cisco.com/docs/contact-center-express/#!cisco-identity-service-client-sdk-guide/during-agent-login
// Get Access Token for the received Authorization Code
String redirectURI = config.getRedirectUri();
AccessToken token = client.getAccessToken(authCode, redirectURI);
When and where do you redirect the user to Contact Center to authenticate? I observed that Finesse will redirect the user to
https://contactcenter.example.com:8553/ids/v1/oauth/authorize?redirect_uri=https%3A%2F%2Ffinesse.example.com%3A443%2Fdesktop%2Fsso%2Fauthcode&client_id=8a75xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&state=aHR0cHM6Ly92bS1mLWZpbi1hLmRldi5pbi5zcGluc2NpLmNvbS9kZXNrdG9wL2pfaWRlbnRpdHlfY2hlY2s%2FZXJyb3I9dHJ1ZQlhcHBsb2dpbg%3D%3D&response_type=code
But where is it specified to use the identity service (IDS) path /ids/v1/oauth/authorize? And is state a required parameter? And does the IDS SDK handle the callback path /desktop/sso/authcode? I imagine that it doesn't but what are the parameters that will be sent to it? I'm using Spring framework.
Am I to reverse engineer the whole process, or is there additional documentation that I am missing?
Even after I receive an OAuth token, how would I use it to make other REST calls to other Cisco products? The Finesse REST APIs only mention HTTP basic authentication. There is no mention of headers for "Authorization: Bearer" tokens.
https://developer.cisco.com/docs/finesse/#!sign-in-to-finesse/sign-in-to-finesse
I had to reverse engineer it following all the redirects.
#Controller
public class SSOController {
#Autowired
private IdSClientConfigurationImpl config;
#Autowired
private IdSClient client;
#PostMapping("/login")
public String login(#RequestParam(name="user", required=true) String user) {
// redirect the user to the Cisco Contact Center Express Identity Service
String redirectURI = config.getRedirectUri();
String clientId = config.getClientId();
URI uri = UriComponentsBuilder
.fromUriString("https://contact-center-express:8553/ids/v1/oauth/authorize")
.queryParam("redirect_uri", "{redirect_uri}")
.queryParam("client_id", "{client_id}")
// .queryParam("state", "{state}") // base64 encoded
.queryParam("response_type", "code")
.build(redirectURI, clientId);
return "redirect:"+uri.toString();
}
#GetMapping("/idscallback")
public String idscallback(
#RequestParam(name="code", required=true) String code,
#RequestParam(name="state", required=false) String state,
HttpSession session) throws IdSClientException {
// Get Access Token for the received Authorization Code
String redirectURI = config.getRedirectUri();
AccessToken token = client.getAccessToken(code, redirectURI); // why do I need redirectURI when it's already redirected?
String accessTokenString = token.getAccess_token();
session.setAttribute("token", accessTokenString);
// model.addAttribute("token", accessTokenString);
return "redirect:/";
}
And in a bean far, far away...
#Bean
public IdSClientConfigurationImpl config() throws IOException, IdSClientException {
ClassPathResource idsclientResource = new ClassPathResource("idsclient.properties");
IdSClientConfigurationImpl config = new IdSClientConfigurationImpl(idsclientResource.getFile().getPath());
// IdSClientConfigurationImpl config = new IdSClientConfigurationImpl("src/main/resources/idsclient.properties");
config.load();
return config;
}
#Bean
public IdSClient setupIdsClient() throws IOException, IdSClientException {
IdSClient client = IdSClientFactory.getIdSClient();
client.setTLSContext(createSSLTrustManager(), createHostnameVerifier());
// client.setTLSContext(arg0, arg1) // use secure trust manager and hostname verifier in production
client.init(config);
return client;
}
private X509TrustManager createSSLTrustManager() {
X509TrustManager tm = new TrustAllX509TrustManager();
return tm;
}
private HostnameVerifier createHostnameVerifier() {
HostnameVerifier hv = new SkipAllHostNameVerifier();
return hv;
}
I am new to the Authorized.net API and facing the below E00007, User authentication failed due to invalid authentication values. in authorized.net. I am using the authorize.net version to call the GetTransactionDetails API.
Any idea on what is the issue ? Any help ?
<dependency>
<groupId>net.authorize</groupId>
<artifactId>anet-java-sdk</artifactId>
<version>1.8.6</version>
</dependency>
and I am using the below code
public class GetTransactionDetails {
public static final String apiLoginId= "6LaBc8HJ6Q";
public static final String transactionKey= "XXXXXXXX";
public static void main(String[] args) {
ApiOperationBase.setEnvironment(Environment.SANDBOX);
MerchantAuthenticationType merchantAuthenticationType = new MerchantAuthenticationType() ;
merchantAuthenticationType.setName(apiLoginId);
merchantAuthenticationType.setTransactionKey("transactionKey");
ApiOperationBase.setMerchantAuthentication(merchantAuthenticationType);
//need valid transacaction Id to run
String transId = "60024624183";
GetTransactionDetailsRequest getRequest = new GetTransactionDetailsRequest();
getRequest.setMerchantAuthentication(merchantAuthenticationType);
getRequest.setTransId(transId);
GetTransactionDetailsController controller = new GetTransactionDetailsController(getRequest);
controller.execute();
GetTransactionDetailsResponse getResponse = controller.getApiResponse();
TransactionDetailsType transactionDetailsType = getResponse.getTransaction();
if (getResponse!=null) {
if (getResponse.getMessages().getResultCode() == MessageTypeEnum.OK) {
System.out.println(getResponse.getMessages().getMessage().get(0).getCode());
System.out.println(getResponse.getMessages().getMessage().get(0).getText());
System.out.println("---------------------------------------");
System.out.println("Auth Amount : "+transactionDetailsType.getAuthAmount());
System.out.println("Auth Code : "+transactionDetailsType.getAuthCode());
System.out.println("Response Reason Description : "+transactionDetailsType.getResponseReasonDescription());
System.out.println("Transaction Status : "+transactionDetailsType.getTransactionStatus());
System.out.println("Submit Date : "+transactionDetailsType.getSubmitTimeLocal());
}else{
System.out.println("Failed to get transaction details: " + getResponse.getMessages().getResultCode());
List<Message> messages = getResponse.getMessages().getMessage();
for (Message message : messages) {
System.out.println("Code : "+message.getCode());
System.out.println("Text : "+message.getText());
}
}
}
}
}
output:
06/02/17 00:35:48,733: INFO [pool-1-thread-1] (net.authorize.util.LogHelper:24) - Use Proxy: 'false'
Failed to get transaction details: ERROR
Code : E00007
Text : User authentication failed due to invalid authentication values.
Can you try removing the quotes from setTransactionKey
merchantAuthenticationType.setTransactionKey("transactionKey");
change to
merchantAuthenticationType.setTransactionKey(transactionKey);
There are multiple causes of this error, which may include:
Using the wrong API Login ID (the "name" field in some of the API calls)
Using the wrong Transaction Key
Using the wrong API endpoint. Authorize.net has two API endpoints, one for sandbox and one for production:
Sandbox API Endpoint: https://apitest.authorize.net/xml/v1/request.api
Production API Endpoint: https://api.authorize.net/xml/v1/request.api
To test your Authorize.net authentication credentials, go to [Authorize.net's API documentation site] and choose API Endpoints and Authentication, then the test your authentication credentials box.1
I'm building an application that needs access to our clients' Office 365 Management Activities. I've followed the steps outlined in this Azure Active Directory overview, and am able to use the OAuth code to acquire an initial Access Token, as well as use this token to set up O365 subscriptions.
However, when I use the refresh_token provided with my initial token to acquire a new Access Token, I get the following error:
{"error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '8f72f805-dfd2-428d-8b0e-771a98d26c16'. Send an interactive authorization request for this user and resource.\r\nTrace ID: df229c3f-8f28-420b-9ac3-321ab1b2ad09\r\nCorrelation ID: 0e0f2bcb-4b19-458a-8556-2a6d4e51379f\r\nTimestamp: 2016-10-03 17:33:20Z","error":"invalid_grant"}
Since I'm able to acquire and use the initial Access Token, I'm pretty sure that the user is granting my applications some permissions. Is there a specific permission that I need in order to acquire a new Access Token using the Refresh Token?
Edit:
Specifically, I'm using the com.microsoft.azure::adal4j java package, AuthenticationContext class, acquireTokenByAuthorizationCode and acquireTokenByRefreshToken methods:
public class AzureProvisioner {
private final AuthenticationContext authService = new AuthenticationContext(
"https://login.windows.net/common/oauth2/token", true, Executors.newSingleThreadExecutor());
private final ClientCredential clientCredential = new ClientCredential("azureAppId", "azureAppSecret");
public static final String resource = "https://manage.office.com";
// Internal implementation of REST interface; Microsoft didn't provide a Java Library
final Office365ManagementApi managementApi;
public void acquireToken(final String authCode, final URI redirectUri) {
final AuthenticationResult authResult = authService.acquireTokenByAuthorizationCode(
authCode, redirectUri, clientCredential, resource, null).get()
// internal library code, gets the "tid" field from parsing the JWT token
final String tenantId = JwtAccessToken.fromToken(authResult.getAccessToken()).getTid();
// works
createInitialSubscription(customerId, authResult.getAccessToken(), tenantId);
// throws an error
final AuthenticationResult refreshResult = authService.acquireTokenByRefreshToken(
authResult.getRefreshToken(), clientCredential, null).get();
}
private void createInitialSubscription(final String accessToken, final String tenantId) {
final String authHeader = "Authorization: Bearer " + accessToken;
final String contentType = "Audit.AzureActiveDirectory";
// internal implementation
final CreateWebhookRequest requestBody = new CreateWebhookRequest();
managementApi.createSubscription(authHeader, tenantId, contentType, requestBody);
}
}
The same code, without any external dependencies, also does not work for me:
public class AzureProvisioner {
private final AuthenticationContext authService = new AuthenticationContext(
"https://login.windows.net/common/oauth2/token", true, Executors.newSingleThreadExecutor());
private final ClientCredential clientCredential = new ClientCredential("8f72f805-dfd2-428d-8b0e-771a98d26c16", "secret");
public final String resource = "https://manage.office.com";
private URI redirectUri = new URI("https://localhost");
private static final String oAuthUrl = "https://login.windows.net/common/oauth2/authorize?response_type=code&client_id=8f72f805-dfd2-428d-8b0e-771a98d26c16&resource=https%3A%2F%2Fmanage.office.com&redirect_uri=https%3A%2F%2Flocalhost";
public AzureProvisioner() throws Exception {
// do nothing
}
public static void main(String... args) throws Exception {
final String authCode = "AQABAAAAAADRNYRQ3dhRSrm...";
new AzureProvisioner().acquireToken(authCode);
}
public void acquireToken(final String authCode) throws Exception {
final AuthenticationResult authResult = authService.acquireTokenByAuthorizationCode(
authCode, redirectUri, clientCredential, resource, null).get();
System.out.println(authResult.getAccessToken());
// throws an error
final AuthenticationResult refreshResult = authService.acquireTokenByRefreshToken(
authResult.getRefreshToken(), clientCredential, resource, null).get();
System.out.println(refreshResult.getAccessToken());
}
}
Using a proxy, I took a trace of the https refresh request:
Method: POST
Protocol-Version: HTTP/1.1
Protocol: https
Host: login.windows.net
File: /common/oauth2/token
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 876
refresh_token={token}
&resource=https%3A%2F%2Fmanage.office.com
&grant_type=refresh_token
&scope=openid
&client_secret={secret}
&client_id=8f72f805-dfd2-428d-8b0e-771a98d26c16
It turns out that the root issue was with my application permissions. Under My Application > Settings > Required Permissions > Office 365 Management APIs, I had selected the "Application Permissions", where I needed to select the "Delegated Permissions". Swapping those over, my code immediately started working as expected.
ADAL uses the stored refresh tokens automatically and transparently, you aren't required to perform any explicit action. AcquireTOkenByRefreshToken is in the ADAL surface for legacy reasons, and has been removed from version 3.x. More background at http://www.cloudidentity.com/blog/2015/08/13/adal-3-didnt-return-refresh-tokens-for-5-months-and-nobody-noticed/
I'm trying to use oauth in a redmine 2.4.2 with the redmine_oauth_provider plugin (https://github.com/a-ono/redmine_oauth_provider).
I have configure a new client in redmine and get then the consumer key and consumer secret.
I try then to make an example using the scribe library (used by jenkins to make the oauth work).
But I can't get the request token, redmine send me back a 401 with body Invalid OAuth Request.
Here is the Service I wrote
package org.scribe.builder.api;
import org.scribe.model.Token;
public class RedmineApi extends DefaultApi10a {
protected final String redmineUrl;
public RedmineApi(String redmineUrl) {
redmineUrl = redmineUrl.trim();
if (!redmineUrl.endsWith("/")) {
redmineUrl += "/";
}
this.redmineUrl = redmineUrl;
}
#Override
public String getAccessTokenEndpoint() {
return redmineUrl + "access_token";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return redmineUrl + "authorize?oauth_token=" + requestToken.getToken();
}
#Override
public String getRequestTokenEndpoint() {
return redmineUrl + "request_token";
}
}
And the client test
OAuthService service = new ServiceBuilder()
.provider(new RedmineApi("https://nuiton.org/oauth"))
.apiKey("XXX")
.apiSecret("XXX")
.debug()
.build();
Token requestToken = service.getRequestToken();
At runtime I got
using Http Header signature
sending request...
response status code: 401
Exception in thread "main" org.scribe.exceptions.OAuthException: Response body is incorrect. Can't extract token and secret from this: 'Invalid OAuth Request'
And on the redmine side I got
Started POST "/oauth/request_token" for 78.216.18.159 at Wed Feb 05 22:30:13 +0100 2014
Processing by OauthController#request_token as HTML
Current user: anonymous
Rendered text template (0.0ms)
Filter chain halted as # <OAuth::Controllers::ApplicationControllerMethods::Filter:0xf533d024 #options={:interactive=>false, :strategies=>:two_legged}, #strategies=[:two_legged]> rendered or redirected
Completed 401 Unauthorized in 3.5ms (Views: 0.6ms | ActiveRecord: 0.6ms)
Any help will be much appreciated.