I want to integrate office365 service management API for collecting events from it.I want to use client credential way to use service to service call but i am getting following error,
{
"error":"invalid_client",
"error_description":"AADSTS50048: Subject must match Issuer claim in the client assertion.
\r\nTrace ID: 1ad7acd8-3945-4fe0-a313-07638eb76e42\r\nCorrelation ID: a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa\r\nTimestamp: 2016-06-09 07:20:15Z",
"error_codes":[50048
],
"timestamp":"2016-06-09 07:20:15Z",
"trace_id":"1ad7acd8-3945-4fe0-a313-07638eb76e42",
"correlation_id":"a6c3a3c9-b737-4bfc-894f-3086c3ce8dfa"
}
i use following doc to integration,
For getting client assersion,
https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx I am getting this. But for Access token,
https://msdn.microsoft.com/en-us/library/office/dn707383.aspx I not getting this as a response getting above error.
Somebody help me please :)
How did you get the client_assertion? The link you provide doesn’t describe how to get the ‘client_assertion’. It acquire the token with the app’s id and secret which is doesn’t support for the Office 365 Management API. You can refer the blog to about the ‘client_assertion’.
And here is an C# code sample which use the ADAL to get the access token for the client credentials flow:
string clientId = "{clientId}";
string certThumbprint = "{copy from mmc}";
certThumbprint = certThumbprint.Replace("\u200e", string.Empty).Replace("\u200f", string.Empty).Replace(" ", string.Empty);
string apiResourceId = "https://manage.office.com";
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
string authority = "https://login.windows.net/{yourTentant}";
var authContext = new AuthenticationContext(authority);
try
{
store.Open(OpenFlags.ReadOnly);
cert = store.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false)[0];
}
finally
{
store.Close();
}
var certCred = new ClientAssertionCertificate(clientId, cert);
AuthenticationResult result = null;
try
{
result = await authContext.AcquireTokenAsync(apiResourceId, certCred);
}
catch (Exception ex)
{
}
Related
I want to pass a JWT token from a NodeJS service to another service in Java. However, based on the what I've tried, the token is always invalid whenever I try to verify it on the Java side. I do understand the JWT is platform-independent but I'm not able to figure out why is the token not able to get verified on the Java side.
Error: io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted
NodeJS signing the token (using express-jwt library)
const jwtPayload = { id: "admin" };
const secret = " ... some secret ...";
const jwtData = { expiresIn: 2h };
const access_token = jwt.sign(jwtPayload, secret, jwtData);
Java verifying the token (using io.jsonwebtoken)
String secret = "...same as on the nodejs side"
String accessToken = " .. access_token from nodejs .. "
String username = Jwts.parserBuilder().setSigningKey(secret).build().parseClaimsJws(accessToken).getBody().getSubject();
I have not set any additional options either on the NodeJS side or the Java side. Am I missing some configuration on either of the platforms? Or should I be using a different library?
In my case, solved like this:
GENERATE JWT IN EXPRESS:
jwt.sign({ issuer: new Date(), roles, exp: Math.floor(Date.now() / 1000) + (43200) }, SECRET, {
algorithm: 'HS256',
subject: username,
jwtid: jwtId,
}, (err, token) => {
if (err) {
logger.error(util.inspect(err));
}
resolve({ token, jwtId });
});
IN JAVA I READ USING "SECRET".getBytes("UTF-8"):
Claims claims = Jwts.parser().setSigningKey("SECRET".getBytes("UTF-8")).parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
I think the issue is the string secret. By calling getBytes("UTF-8") on your secret and providing signWith() with the byte[], everything will work out.
String username = Jwts.parser()
.setSigningKey(secret.getBytes("UTF-8"))
.parseClaimsJws(accessToken)
.getBody()
.getSubject();
(Also need to catch the UnsupportedEncodingException!)
So basically I need to use embedded signing feature to get the URL and embed into my application, and then my customer can sign the document from my side. Apart from that, after my customer signed on the doc, he needs to ask his debtor to sign on the same doc as well.
So on DocuSign UI, I found that I can set a signing order, which means the second recipient receives the email right after the first recipient signed (perfect match my requirement).
setting on UI
However, the second recipient can not receive the email after the first signer signed even though on UI it says sent.
public Envelope embeddedSigning(Long debtorId, String signerEmail, String signerName, String templateId) throws ApiException, IOException {
// create an envelop
EnvelopeDefinition envelope = makeEnvelope(debtorId, signerEmail, signerName, templateId);
ApiClient apiClient = baseRestApiClient();
apiClient.addDefaultHeader("Authorization", "Bearer " + getToken());
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
EnvelopeSummary summary = envelopesApi.createEnvelope(accountId, envelope);
RecipientViewRequest viewRequest = makeRecipientViewRequest(debtorId, signerEmail, signerName);
ViewUrl viewUrl = envelopesApi.createRecipientView(accountId, summary.getEnvelopeId(), viewRequest);
// #formatter:off
return Envelope.builder()
.envelopId(summary.getEnvelopeId())
.redirectUrl(viewUrl.getUrl()).build();
// #formatter:on
}
private EnvelopeDefinition makeEnvelope(Long debtorId, String signerEmail, String signerName, String templateId) throws IOException {
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
envelopeDefinition.setEmailSubject("Please sign this document");
envelopeDefinition.setTemplateId(templateId);
TemplateRole signer = new TemplateRole();
signer.setEmail(signerEmail);
signer.setName(signerName);
signer.clientUserId(String.valueOf(debtorId));
signer.setRoleName("signer0");
signer.setRoutingOrder("1");
TemplateRole signer1 = new TemplateRole();
signer1.setEmail("xxx");
signer1.setName("xxx");
signer1.clientUserId(String.valueOf(xxx));
signer1.setRoleName("signer1");
signer1.setRoutingOrder("2");
envelopeDefinition.setTemplateRoles(Arrays.asList(signer, signer1));
envelopeDefinition.setStatus("sent");
return envelopeDefinition;
}
You are setting signer1.clientUserId(String.valueOf(xxx)); which means you are making signer an embedded signer. By Default, DocuSign does not send email to the embedded signer. By making a signer as embedded signer, you are telling DocuSign that calling App will take care of deciding when to host signing ceremony for this signer so DocuSign will not send an email as they will not be doing signing from the email, instead it be your App which will be generating Signing URL when that signer is on your App. So if you remove signer1.clientUserId(String.valueOf(xxx)); code then you will see that signer1 will get an email from DocuSign.
Docs has more details about embedded signing.
Typically routing order starts at 1. so it should be 1 and 2, not 0 and 1.
Apart from that, "Sent" is the status for the entire envelope. The envelope goes to routing order 1 first. Then, when all recipients of routing order 1 finished signing, it goes to 2 etc. I'm not sure if you actually have an issue here, but please confirm after you changed to 1 and 2 what exactly do you see that you don't expect.
I am hitting the REST API server as a client using Swift 3 programming, I have sent request once and a single response. But the problem is once i posted my data's the data's are inserted twice and getting the response based on the second insert value.
For Example: When i posted new mail address, it inserted into Database, and it iterated again and trying to insert again and i get the response as "Email is already registered". I have tried all the methods from my client side programming.
Few have said that the server by itself restarted again after 40 sec, i'm not sure if that is the case how to overcome this problem.
CODE IN SWIFT 3 CLIENT:(iOS)
func getMailAddress(mailID: String) {
let username = "admin"
let password = "admin"
let loginString = String(format: "%#:%#", username, password)
let loginData: NSData = loginString.data(using: String.Encoding.utf8)! as NSData
let base64LoginString = loginData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let getUrl = URL(string: "http://localhost/rest/merchantsignup/mailExists/\(mailID)")
var request = URLRequest(url: getUrl!)
request.httpMethod = "GET"
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let urlConnection = NSURLConnection(request: request, delegate: self)
urlConnection?.start()
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
} else {
do {
let myJSON = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)
print("myJSON:\(myJSON)")
} catch let err as NSError {
print(err)
}
}
}
task.resume()
}
CODE IN JAVA REST WEBSERVICES:
#GET
#Path("/mailExists/{emailId}")
#Produces(MediaType.APPLICATION_JSON)
public RestResMessagesVO mailExists(#PathParam("emailId")String emailId){
System.out.println(emailId);
MerchantRegistrationDAO mcdao = new MerchantRegistrationDAO();
RestResMessagesVO resObj = new RestResMessagesVO();
resObj.setMessage(mcdao.ismcEmailorPhoneExists("emailAddress",emailId.trim()));
return resObj;
}
You are trying to establish a connection with basic authentication, but actual problem here, while your requesting your server it get hitted twice is
1. you established your connection using request so, by that time it hitted the server once.
2. Then you created an object for NSURLConnection, and you started the connection, by that it hits the server second time.
Because of this only you hit your server twice, and get the response based on the second server hit.
Solution: Try this to overcome your Problem:
let username = "admin"
let password = "admin"
let loginString = String(format: "%#:%#", username, password)
let loginData: NSData = loginString.data(using: String.Encoding.utf8)! as NSData
let base64LoginString = loginData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let getUrl = URL(string: "Your URL String")
var request = URLRequest(url: getUrl!)
request.httpMethod = "GET"
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request)
{ (data, response, error) in
if error != nil
{
print(error!)
}
else
{
do {
let JSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print("YOUR RESPONSE: \(JSON)")
}
catch let err as NSError
{
print(err)
}
}
}
task.resume()
probably that's because you are calling
urlConnection?.start()
and
task.resume()
I have created web service client using Apache axis 1.4. The wcf service i am accessing is STS service which required AppliesTo Parameter and its return SAML token. I have go through various blog and website while searching and some how i came to this kanbancoding Part 3
So i go through it and do the changes in my code but now i am getting org.apache.cxf.ws.policy.PolicyException: None of the policy alternatives can be satisfied. My
Well after lot of try and error i figure out what exactly i need to call WCF STS Service. While goggling i found a document on Docs.Oasis OOasis WS Trust 1.3 which explain in details what data need to be send in a soap Message and yes with the help of kanbancoding this is my method to call the STS
private static void getSecurityToken() {
try {
// Use the empty constructor – no need to specify wsdl
SecurityTokenService src = new SecurityTokenService();
// Pull the class used to negotiate WS Trust directly from the
// SecurityTokenService
IWSTrust13Sync trust = src.getBasicHttpBindingIWSTrust13Sync();
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IWSTrust13Sync.class);
factory.setAddress(ServiceURL);
IWSTrust13Sync service = (IWSTrust13Sync) factory.create();
// Obtain a reference to the CXF endpoint using the ClientProxy helper:
Client client = ClientProxy.getClient(service);
// Set up logging if desired
client.getOutInterceptors().add(new LoggingOutInterceptor());
client.getInInterceptors().add(new LoggingInInterceptor());
client.getRequestContext().put("com.sun.xml.ws.connect.timeout", 1 * 60 * 1000);
client.getRequestContext().put("com.sun.xml.ws.request.timeout", 5 * 60 * 1000);
// Specify the user we want to authenticate
client.getRequestContext().put("ws-security.username", UserName);
client.getRequestContext().put("ws-security.password", Password);
HTTPConduit http = (HTTPConduit) client.getConduit();
http.getAuthorization().setUserName(UserName);
http.getAuthorization().setPassword(Password);
http.getClient().setConnectionTimeout(36000);
http.getClient().setAllowChunking(false);
RequestSecurityTokenType token = new RequestSecurityTokenType();
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element tokenType = document.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512",
"TokenType");
tokenType.setTextContent("http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0");
token.getAny().add(tokenType);
Element requestType = document.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512",
"RequestType");
requestType.setTextContent("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue");
token.getAny().add(requestType);
Document appliesTodoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element appliesTo = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/09/policy",
"AppliesTo");
Element endPoint = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/08/addressing",
"EndpointReference");
Element address = appliesTodoc.createElementNS("http://schemas.xmlsoap.org/ws/2004/08/addressing",
"Address");
address.setTextContent("http://localhost");
endPoint.appendChild(address);
appliesTo.appendChild(endPoint);
token.getAny().add(appliesTo);
//Now specify what claims we want back.
Document claimsDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element claims = claimsDoc.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "Claims");
claims.setAttribute("Dialect", "http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice");
// Add claims to token request
//token.getAny().add(claims);
RequestSecurityTokenResponseCollectionType result = service.trust13Issue(token);
//parseResponse(result);
List<RequestSecurityTokenResponseType> response = result.getRequestSecurityTokenResponse();
Iterator<RequestSecurityTokenResponseType> itr = response.iterator();
while (itr.hasNext()) {
RequestSecurityTokenResponseType obj = itr.next();
List<Object> responseObject = obj.getAny();
Iterator<Object> ObjItr = responseObject.iterator();
while (ObjItr.hasNext()) {
System.out.println("Result " + ObjItr.next());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
But not fully succeeded in what i want but yes something i am getting in response In Apache CFX Log not in result object.
H!I am having a very hard time with Yahoo Oauth right now.
So here's the problem, I am using scribe 3.1.5 and followed Yahoo's documentations(apparently they use Oauth1.0), I've been able to get the request token, then trade for the access token with the verifier. The problem emerges when I try to get user's GUID from URL http://social.yahooapis.com/v1/me/guid?format=json with the access token.
now, what's interesting is that, yahoo would sometimes give me the GUID back, and sometimes give me a "invalid signature" error. Sometimes I get 5 invalid signatures in a row, sometimes I get 15 successful calls in a row, most of the time it is like 40% invalid signatures and 60% success. What is even weirder is that sometimes I get a success when fetching GUID, but when i try to fetch user's profile IMMEDIATELY after the success with the identical access token and GUID, it gives me an invalid sigature...(wtf)
so here's the code I use:
Redirecting User:
Token requestToken = yahooService.getRequestToken();
getSession().setAttribute("yahooRequestToken", requestToken);
String authenticationUrl = yahooService.getAuthorizationUrl(requestToken);
redirect(authenticationUrl);
Getting callback:
#GET #Path("/oauthcallback/yahoo")
public Response yahooCallback(#QueryParam("oauth_token") String oAuthToken, #QueryParam("oauth_verifier") String oAuthVerifier) {
Token requestToken = (Token)getSession().getAttribute("yahooRequestToken");
Token accessToken = yahooService.getAccessToken(requestToken, oAuthVerifier);
UserProfile user = userService.findUserById(getUserId());
try{
//TODO occasioanlly yahoo returns invalid_signature, this is inconsistent and I have no idea why
String guid = yahooService.getGuid(accessToken);
String email = yahooService.getUserEmail(guid, accessToken);
.....
YahooService::Getting Access Token:
[the service object is protected final OAuthService service; in parent class]
#Override
public Token getAccessToken(Token requestToken, String oAuthVerifier) {
Verifier verifier = new Verifier(oAuthVerifier);
return service.getAccessToken(requestToken, verifier);
}
YahooService::Getting GUID:
#Override
public String getGuid(Token accessToken){
OAuthRequest requestA = new OAuthRequest(Verb.GET, GET_YAHOO);
service.signRequest(accessToken, requestA);
Response responseA = requestA.send();
JsonParser parser = new JsonParser();
//sometimes the response body is a invalid signature error message
JsonObject json = (JsonObject)parser.parse(responseA.getBody());
return json.getAsJsonObject("guid").get("value").getAsString();
}
YahooService::Getting User Email:
#Override
public String getUserEmail(String guid, Token accessToken) {
String profileCallUrl = GET_YAHOO_PROFILE.replaceAll("GUID", guid);
OAuthRequest requestB = new OAuthRequest(Verb.GET, profileCallUrl);
service.signRequest(accessToken, requestB);
requestB.addHeader("realm", "yahooapis.com");
Response responseB = requestB.send();
JsonParser parser = new JsonParser();
//sometimes the response body is a invalid signature error message
JsonObject jsonProfile = (JsonObject)parser.parse(responseB.getBody());
...processing code, error free
}
I know YahooAPI class in Scribe 3.1.5 in maven distribution is like 2 years old, but I doubt it would lead to such inconsistent behavior. Scribe's built in support for Google and Live oauth is basically useless, unfortunately, unlike Google or Hotmail which both have awesome doc so that I could basically figure out everything myself, Yahoo's doc stops at getting the access token, I can not find useful explanation on why I would get an invalid signature SOMETIMES with my access token
Please help! Thanks in advance
Its looks like Yahoo issue, I have same error message since few days :
http://developer.yahoo.com/forum/OAuth-General-Discussion-YDN-SDKs/signature-invalid-when-making-calls-to-the/1385735171123-8a38d8cf-815b-43ac-9d77-5bd2f2f60796
There is no need to ask for GUID to yahoo as yahoo returns GUID of the currently logged in user at the time of giving you the access token so if you have a access token you also have a GUID in the response.
Refer this