I learn how to use oauth2 from the example sparklr2, but it use inMemoryClientDetailsService. which is not the case for production, an oauth2 webapp like twitter should let new client to register. so eventually will use JdbcClientDetailsService. but the example and documentation of spring security oauth2 does not provide what is the correct way to do registration in code.
here is what I guess from looking at the project source.
JdbcClientDetailsServiceBuilder client = new JdbcClientDetailsServiceBuilder();
client.dataSource(dataSource)
.withClient("my-trusted-client-with-secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret("somesecret");
client.build();
it writes a record to the database oauth_client_details table, but I want to know if I am doing it correctly (best practice)? does anyone know?
Related
I would like to get/set realtime database rules using Rest API however no tutorial is working for me. I try to do it like that:
I copied the url to my realtime database which is in Europe https://my-project-database.europe-west1.firebasedatabase.app/
I copied the java code from this tutorial: https://firebase.google.com/docs/database/rest/auth which was supposed to give me the access token
val googleCred = GoogleCredential.fromStream(File("/path/to/my/key.json").inputStream())
val scoped = googleCred.createScoped(
Arrays.asList( // or use firebase.database.readonly for read-only access
"https://www.googleapis.com/auth/firebase.database",
"https://www.googleapis.com/auth/userinfo.email"
)
)
scoped.refreshToken()
val token = scoped.accessToken
println(token)
However the token looks very strange with a long string of dots at the end like (it's related to: Why am I getting a JWT with a bunch of periods/dots back from Google OAuth?)
ya29.c.Kp8BCgi0lxWtUt-_[Normal JWT stuff, redacted for
security]yVvGk...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
I did HTTP GET to address like https://my-project-database.europe-west1.firebasedatabase.app/.settings/rules.json?access_token=$token and I got 401 UNAUTHORIZED
I assume it's due to the fact that I use the whole of this strange token full of dots as the access_token variable. So now I have questions how to transform it and use as the access_token to make it work
EDIT:
I created this gist although it's in python it has exactly the same problem. How to make it work ?
https://gist.github.com/solveretur/86d53a9c0221f096c38c3ef8f70a8dbd
It works I used wrong database key
I'm trying to implement the "on behalf of" flow in an application using ADFS 2016 as STS. As a reference, I look at this Microsoft tutorial (https://learn.microsoft.com/en-ca/windows-server/identity/ad-fs/development/ad-fs-on-behalf-of-authentication-in-windows-server). It's working as it should, I can login into my web application and then use my original access token in UserAssertion to generate a new access token with the proper audience to call my API BUT I found absolutely no way to include any user informations (sub, name, email, upn etc.) into the access token for my API, even if I set claim rules into my ADFS configurations for the API.
I checked the communication between my app and adfs using Fiddler and everything looks like the informations in the tutorial. See the screen shot of the "on behalf of" request below :
Here's the resulting access token :
Finally, here's the code I use to generate my new access token :
private async Task<string> GetAccessToken(ClaimsPrincipal user, string originalAccessToken)
{
var authority = "[authority]";
var context = new AuthenticationContext(authority, false);
string userName = user.FindFirstValue("upn");
var userAssertion = new UserAssertion(originalAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer",userName);
var cc = new ClientCredential("https://localhost:44387/", "[client_secret]");
var result = await context.AcquireTokenAsync("https://localhost:44339/", cc, userAssertion);
return result.AccessToken;
}
Have you struggle with that scenario and if yes, did you find a way to fix this ?
Thanks
I've only used the Microsoft On Behalf Of flow with Azure AD and not ADFS, but it looks like you need to send a more detailed scope in your User Info request.
Maybe try sending 'openid profile email', to indicate that you want that type of detail, as in Section 17 of my blog post. Of course this assumes that this type of data has been registered for all users.
TROUBLESHOOTING
Looks like one of these will be the cause:
A suboptimal Microsoft library that does not allow you to send the required scope
Or ADFS 2016 perhaps lacks the scope features that work correctly in Azure AD
I would concentrate on making extra sure you are sending the correct form URL encoded request message, using a tool such as curl, Postman or a plain C# HttpClient. Here is the code I used to send the correct scope - using an open source library rather than a Microsoft one:
Sample NodeJS Code
If you can get the scope sent correctly then you should have a resolution either way:
Either you get the correct data and can update your code
Or the behaviour you want is not supported by ADFS
Good luck ...
We have an instance of Identity Server 3 which has been used for some time with various clients, some using implicit flow, others using client credentials. We now have a new requirement to integrate an iOS native app with this identity provider. I understand these days implicit flow is not recommended and public facing apps should instead be using authorization code flow. Examples of such advice are here and here.
By my understanding, authorization code flow has a step whereby a received authorization code is exchanged for JWT tokens via some back channel by supplying it alongside a client ID and secret. However, with SPAs and native apps we don't have the luxury of storing secrets. The guidance I found here would suggest I can simply omit the secret from the connect/token request, but my testing so far doesn't confirm this. So I'm stuck. To demonstrate, I've set up a client on my local instance of IS3 to test with:
{
'clientId': 'test',
'flow': 'AuthorizationCode',
'name': 'test',
'redirectUris': [ 'http://localhost:8080/' ],
'scopes': ['openid','profile']
}
I then make the following GET request to my IdP:
[ID_PROVIDER]/connect/authorize?client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A8080&scope=openid%20profile&response_type=code
This lets me sign in and returns me to my test app running at http://localhost:8080 with my authorization code in the querystring.
I now try to exchange this code for JWT tokens by POSTing to [ID_PROVIDER]/connect/token with the following body: code=[AUTH_CODE]&grant_type=authorization_code&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A8080
But Identity Server rejects this with an HTTP 400 and invalid_client error. When I dig into its logs I see a ClientSecretValidator event with message "No client secret found". Which kind of makes sense based on my understanding outlined above, but given people are recommending using this flow for public-facing apps I must be misunderstanding something.
If anyone could clarify that'd be great, thanks.
You can't just omit the client secret. For your native case, I'd consider embedding the secret within the app. The authorize request will still have to validate the return_uri (custom URI scheme for your native app) and if that still feels insecure, you can also lean on Proof of possession (PoP) tokens (https://identityserver.github.io/Documentation/docsv2/pop/overview.html).
For a SPA app I would keep it implicit flow, I see no point in doing secrets there.
I have a google cloud endpoint api application which i want to call it from another google app engine web application, say from a servlet. The cloud endpoint api is not secured.
I tried looking for examples but could not find one. I see example related to Android client.
When tried using URLConnection it does not work, am not sure whether am doing correctly as well, sample codes or pointers will be of great help. I also checked the logs of cloud endpoint api to see if any requests are coming through, but i don't see any errors in the logs.
I'm doing this as well, although with authentication. You can use the Jar generated by the endpoint API at MyAPI/build/libs/MyAPI-v1-SNAPSHOT.jar, just as you might in Android.
Once you depend on that JAR, your code to build an API client should look something like that below. Mine is using OAuth authentication with a service account, which I'll leave in there because it was the more complicated part which you might eventually need. But without authentication you should just be able to set the credential to null.
HttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
List<String> SCOPES = Arrays.asList(EMAIL_SCOPE);
String SERVICE_ACCCOUNT_ID = "my-account-id#my-app.iam.gserviceaccount.com";
String CREDENTIAL_FILE = "WEB-INF/my-file.p12";
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCCOUNT_ID)
.setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(new File(CREDENTIAL_FILE))
.build();
MyAPI.Builder builder = new MyAPI.Builder(
HTTP_TRANSPORT,
JSON_FACTORY, credential)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://localhost:8080/_ah/api/")
// .setRootUrl("https://my-appengine-url.appspot.com/_ah/api")
MyAPI myAPI = builder.build();
You cannot use URLConnection for making endpoint calls from App Engine. Use FetchURL instead. If you set doNotFollowRedirect, you will receive X-Appengine-Inbound-Appid as header in the called App Engine project. You can trust this header, as Google would strip it off if somebody off App Engine would use it. Make sure you target the yourproject.appspot.com domain, as it won't work with custom domains.
https://cloud.google.com/appengine/docs/java/appidentity/
I have a relatively old Asp.net mvc web project (created around 2012) which used Facebook connect using the AuthConfig.cs file and registered a client as so.
OAuthWebSecurity.RegisterFacebookClient(
appId: WebConfigurationManager.AppSettings["facebookOAuthAppID"],
appSecret: WebConfigurationManager.AppSettings["facebookOAuthAppSecret"]
);
Up until a few days ago when Facebook changed to v2 of their API, all was good but now all is dead when I try to connect. This is where it fails in the account controller.
DotNetOpenAuth.AspNet.AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
Result always returns false, so never continues.
I have found a few examples which inherit IAuthenticationClient and allow you to setup additional scopes etc, and these expose the endpoints that facbook uses. I tried to update these urls to use the new API (v2.3) but still the same error.
Has anyone encountered this and what steps did you do to resolve this?