I'm building a Single Page Application using Spring Social and Spring Security generated by JHipster.
I'm trying to capture the original query parameters after a user has been authenticated by some social authentication provider.
Example:
calling /signin/someprovider?show=someEntityId and after a successful authentication redirects the user to /signup/ , I need a way to fetch 'someEntityID'.
I assume different http calls make it difficult to pass/store the parameters around.
Is there some Spring built-in functionality I can use/reuse or how does one solve this problem?
UPDATE
The thread of requests looks like this:
(1) browser-> http://localhost:9060/signin/authenticationProvider?show=**someEntityId**
<- redirect to https://authenticationProvider... &state=SomeState
(2) browser -> https://authenticationProvider
<- redirect to http://localhost:9060/signin/google?state=SomeState&code=SomeCode
(3) browser-> http://localhost:9060/signin/authenticationProvider?state=SomeState&code=SomeCode
<- redirect to http://localhost:9060/social/signup
(4) browser -> http://localhost:9060/social/signup
This ends up in
#GetMapping("/signup")
public RedirectView signUp(WebRequest webRequest, #CookieValue(name = "NG_TRANSLATE_LANG_KEY", required = false, defaultValue = Constants.DEFAULT_LANGUAGE) String langKey) {
try {
Connection<?> connection = providerSignInUtils.getConnectionFromSession(webRequest);
socialService.createSocialUser(connection, langKey.replace("\"", ""));
At this point it want to call a function with the original parameter someEntityId.
According to google oauth2 redirect_uri with several parameters the ?show=someEntityId parameter should be encoded in the state parameter of the Oauth2 request in order to survive
from (1) to (3). In (3) the state parameter has to be added to the redirect uri, such that the original parameter can be decoded in (4).
It looks like a lot of work, or am I missing something? It would be nice if there would be a way to have a session variable in which I could store the parameters at (1) and fetch them again when in (4).
Since version 1.1.3 Spring Social creates the state parameter on its own and uses it as a CSRF token, see https://pivotal.io/security/cve-2015-5258 - therefore you can (and should not) encode additional parameters in the state parameter.
Instead if the provider sign is enabled with a ProviderSignInController, a ProviderSignInInterceptor can be used to store such parameters intermediately in the session (in preSignIn(...) and postSignIn(...)).
I guess there is a similar approach if a SocialAuthenticationFilter is used.
Related
I have a requirement to integrate with an external authentication provider which they require us to generate the state & nonce and using these parameters as an input for the embedded JS to generate the QR code, this QR code will be scanned by mobile for authentication.
for the standard login with external authentication provider, we call the Challenge() method to redirect to the login page, and the redirect url contains the state & nonce itself, is there a way to generate/get them without redirection?
If I generate random nonce & state at frontend side then scanning the QR code and completed the authentication in mobile, it returned the authentication code and threw "unable to unprotect the message.State." exception at the IS4, I tried to disable the state validation but it does not work.
configureOptions.ProtocolValidator = new OpenIdConnectProtocolValidator()
{
RequireState = false,
RequireStateValidation = false,
};
Any help would be much appreciated.
JIRA provides a way to access the attachments of an issue using basic auth, jwt auth mechanisms. Using which we can download those files. We're able to download the files using both authentication mechanisms.
sample jwt auth:
curl -X GET --url https://{site-name}.atlassian.net/secure/attachment/1001/example.txt -H 'Authorization: jwt '
Issue / Our requirement:
But is there a way to generate temporarily accessible url for the JIRA issue's attachments which will have token embedded into the URI itself. I've added the example of that below
example url:
https://{site-name}.atlassian.net/attachment/1001/example.txt?token={temp_access_token}
While accessing / clicking on the above mentioned url the download should automatically start even if the user isn't logged into their account
Reason for our requirement:
We're creating jira cloud based service / app and one of its feature is providing access to the user's attachments through our application. Our limitation(cloud service cost) is that we can't download all the huge sized attachments and store and manage it. So we're looking for a solution using which user's can download from the JIRA's server directly
In your JWT generation steps, you can define how long the JWT should be valid. And you can attach a JWT to the URL like this: <Jira Base Url>/rest/api/3/...?jwt=.... This way, you could generate a JWT on demand and it'll only be valid for the given time that you define.
In the Java Example on the page Understanding JWT for Connect apps you can see how they are setting the expirationTime. Just do the same, on demand. Here is the important part of the code snippet:
public class JWTSample {
public String createUriWithJwt()
throws UnsupportedEncodingException, NoSuchAlgorithmException {
long issuedAt = System.currentTimeMillis() / 1000L;
long expiresAt = issuedAt + 180L;
/* ... */
JwtJsonBuilder jwtBuilder = new JsonSmartJwtJsonBuilder()
.issuedAt(issuedAt)
.expirationTime(expiresAt)
.issuer(key);
/* ... */
String jwtToken = /* ... */;
String apiUrl = baseUrl + apiPath + "?jwt=" + jwtToken;
return apiUrl;
}
}
Security concern: I'm explicitly mentioning that you should generate these links on demand because you should not set the expiration date to more than 5-10 minutes (which is already quite high). Otherwise an attacker just needs to retrieve your generated link (URLs are often logged somewhere) and is also able to retrieve the attachment as well.
Alternative Approach
Since you mentioned you'll build a service/app, why not chain the attachment download through your service? This way you wouldn't have to expose a JWT which is a potential security threat. For example: you offer a download button in your UI, this sends a HTTP request to your service and your service downloads the attachment and then forwards it to your user. However, this would not comply with your requirement to give access to unauthenticated users - if that's really what you want to do.
I've an issue on this feature.
SignIn action works well with ADFS and return to AuthServices/Acs
But Logout action don't call ADFS and redirect directly to returnUrl parameters (checked it with fiddler).
I'm calling this link : /AuthServices/Logout?ReturnUrl=~/&Status=LoggedOut
web.config is set up as this :
<kentor.authServices entityId="https://localhost:2181/AuthServices" returnUrl="https://localhost:2181/">
<identityProviders>
<add
entityId="https://ADFS DOMAIN/adfs/services/trust"
signOnUrl="https://ADFS DOMAIN/adfs/ls"
logoutUrl="https://ADFS DOMAIN/adfs/ls/?wa=wsignout1.0"
binding="HttpPost"
allowUnsolicitedAuthnResponse="true"
metadataLocation="https://ADFS DOMAIN/FederationMetadata/2007-06/FederationMetadata.xml"
wantAuthnRequestsSigned="true">
<signingCertificate fileName="~/App_Data/*****.cer" />
</add>
</identityProviders>
</kentor.authServices>
If I launch https://ADFS DOMAIN/adfs/ls/?wa=wsignout1.0 on another tabs, it is working, I return on signin page from my website.
So it seems to be an internal issue to retrieve logouturl and send it ?
Thanks for helps.
There are a number of requirements that need to be met before logout request will be issued:
You need to have a http://kentor.se/AuthServices/LogoutNameIdentifier claim and its issuer has to match the IDP that you're trying to logout from.
You need to have http://kentor.se/AuthServices/SessionIndex claim.
Your AuthServices IDP configuration needs a logoutUrl (I see you've specified this but probably it's easier to let AuthServices read it from the metadata)
You have specified a ServiceCertificate with either Signing or Both usage (i.e. not just Encryption)
Your AuthServices IDP configuration has DisableOutboundLogoutRequests =
false (this is the default)
Missing claims (first two points) is the most likely issue if you have some claims transformation happening during login or you are not retaining the original ClaimsIdentity. See also the documentation regarding ClaimsAuthenticationManager, e.g. https://github.com/KentorIT/authservices/blob/master/doc/ClaimsAuthenticationManager.md
You can turn on logging and see which of these points are failing:
https://github.com/KentorIT/authservices/blob/v0.21.2/Kentor.AuthServices/WebSSO/LogOutCommand.cs#L155-L170
Am trying to use the valance api to call few methods. Am authenticating using https://apitesttool.desire2learnvalence.com from where am getting UserId & UserKey. Now am confused what should i pass in the x_a - x_d parameters for getting the organization info.
What ever i pass i get a 403 forbidden & incorrect token exception.
Some body please help. Am passing folling in the parameters.
x_a : Application ID
x_b : User ID( I got this from https://apitesttool.desire2learnvalence.com)
x_c : private String calculateParameterExpectation( String key, String httpMethod, String apiPath, long timestamp)
{
String unsignedResult = String.format("%s&%s&%s", httpMethod, apiPath, timestamp);
System.out.println(unsignedResult);
String signedResult = D2LSigner.getBase64HashString(key, unsignedResult);
return signedResult;
} Where key is the App Key
x_d : private String calculateParameterExpectation(
String key, String httpMethod, String apiPath, long timestamp) {
String unsignedResult = String.format("%s&%s&%s", httpMethod, apiPath, timestamp);
System.out.println(unsignedResult);
String signedResult = D2LSigner.getBase64HashString(key, unsignedResult);
return signedResult;
} Where key is the User Signature that i got from https://apitesttool.desire2learnvalence.com
Am not sure what is done wrong.
Please note that each back-end service generates a unique UserID/Key pair to go with each user and each application ID, upon request by a call from that application ID.
This explicitly means that User ID/Key pairs are not transferrable from one application to another. Nor are they transferrable from one back-end service to another -- every API-using application should request its own UserID/Key pair for making calls on behalf of each distinct user. Even if you used your App ID/Key when using the api-test tool, unless you pointed the tool at the same back-end service you're actually making the API calls against, you won't get back a UserID/Key pair you can use for later making the API calls (against another service).
Please also note that the signing mechanism requires that you use the upper-case version of the http-method string (thus GET, not get), and it requires that you use the lower-case version of the api path string (thus /d2l/auth/api/token, not /D2L/AUTH/API/TOKEN). If you're pointing the api-test tool at the same LMS you're wanting to make API calls against, and you're using the same App ID/Key pair with the api-test tool as you're using in your production code, then I would seek to make sure that you're formatting your base string exactly right for signing.
I would also encourage you to make fuller use D2L's own client SDK libraries for doing the app/user context management and signing, rather than just using the raw signing call from within the library.
I'd like to have a dynamic redirect URL for my Facebook OAuth2 integration. For example, if my redirect URL is this in my Facebook app:
http://www.mysite.com/oauth_callback?foo=bar
I'd like the redirect URL for a specific request be something like this, so that on the server, I have some context about how to process the auth code:
http://www.mysite.com/oauth_callback?foo=bar&user=6234
My redirect gets invoked after the authorization dialog is submitted, and I get back an auth code, but when I try to get my access token, I'm getting an OAuthException error back from Facebook. My request looks like this (line breaks added for clarity):
https://graph.facebook.com/oauth/access_token
?client_id=MY_CLIENT_ID
&redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar%26user%3D6234
&client_secret=MY_SECRET
&code=RECEIVED_CODE
All of my parameters are URL-encoded, and the code looks valid, so my only guess is that the problem parameter is my redirect_uri. I've tried setting redirect_uri to all of the following, to no avail:
The actual URL of the request to my site
The URL of the request to my site, minus the code parameter
The URL specified in my Facebook application's configuration
Are custom redirect URI parameters supported? If so, am I specifying them correctly? If not, will I be forced to set a cookie, or is there some better pattern for supplying context to my web site?
I figured out the answer; rather than adding additional parameters to the redirect URL, you can add a state parameter to the request to https://www.facebook.com/dialog/oauth:
https://www.facebook.com/dialog/oauth
?client_id=MY_CLIENT_ID
&scope=MY_SCOPE
&redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar
&state=6234
That state parameter is then passed to the callback URL.
If, for any reason, you can't use the option that Jacob suggested as it's my case, you can urlencode your redirect_uri parameter before passing it and it will work, even with a complete querystring like foo=bar&morefoo=morebar in it.
I was trying to implement a Facebook login workflow against API v2.9 following this tutorial. I tried the solutions described above. Manuel's answer is sort of correct, but what I observed is url encoding is not needed. Plus, you can only pass one parameter. Only the first query parameter will be considered, the rest will be ignored. Here is an example,
Request a code via https://www.facebook.com/v2.9/dialog/oauth?client_id={app-id}&redirect_uri=http://{url}/login-redirect?myExtraParameter={some-value}
You'd get a callback for your url. It will look like http://{url}/login-redirect?code={code-from-facebook}&myExtraParameter={value-passed-in-step-1}. Note that facebook would make a callback with myExtraParameter. You can extract the value for myExtraParameter from callback url.
Then you can request access token with https://graph.facebook.com/v2.9/oauth/access_token?client_id={app-id}&client_secret={app-secret}&code={code-from-facebook}&redirect_uri=http://{url}/login-redirect?myExtraParameter={value-extracted-in-step-2}
Additional parameter passed in step 1 after the first query parameter will be ignored. Also make sure to not include any invalid characters in your query parameter (see this for more information).
You're best off specifying a unique callback for each oAuth provider, /oauth/facebook, /oauth/twitter etc.
If you really want the same file to respond to all oAuth requests, either include it in the individual files or setup a path that will call the same file on your server using .htaccess redirects or something similar: /oauth/* > oauth_callback.ext
You should set your custom state parameter using the login helper as such:
use Facebook\Facebook;
use Illuminate\Support\Str;
$fb = new Facebook([
'app_id' => env('FB_APP_ID'),
'app_secret' => env('FB_APP_SECRET'),
'default_graph_version' => env('FB_APP_VER'),
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = [
'public_profile',
'user_link',
'email',
'read_insights',
'pages_show_list',
'instagram_basic',
'instagram_manage_insights',
'manage_pages'
];
$random = Str::random(20);
$OAuth2Client = $fb->getOAuth2Client();
$redirectLoginHelper = $fb->getRedirectLoginHelper();
$persistentDataHandler = $redirectLoginHelper->getPersistentDataHandler();
$persistentDataHandler->set('state', $random);
$loginUrl = $OAuth2Client->getAuthorizationUrl(
url('/') . '/auth/facebook',
$random,
$permissions
);
Hey if you are using official facebook php skd then you can set custom state param like this
$helper = $fb->getRedirectLoginHelper();
$helper->getPersistentDataHandler()->set('state',"any_data");
$url = $helper->getLoginUrl($callback_url, $fb_permissions_array);