Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Jan 25, 2019. It is now read-only.

Conversation

@vinayvishal
Copy link
Contributor

Demonstrates built-in DatabaseIdentityStore usage as specified in JSR 375. Details can be found in the README of this example.

@vinayvishal
Copy link
Contributor Author

@bbuerkle, this is the first example demonstrating usage of built-in DatabaseIdentityStore. Details on how the application works and how JSR 375 plays a role is captured in README of this application.

@bbuerkle
Copy link

Vinay - I can only comment on the grammar. Is that what you would like me to do? Also- I think you should add Will Hopkins to this review.
Thanks,
Barbara

Copy link
Member

@wmhopkins wmhopkins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks great. I do have a few comments on ways we can better illustrate the API, and I think we need to eliminate the PlaintextPasswordHash. In general, we should be illustrating secure ways of doing things, not insecure ways. Is an LDAP example feasible? I think LDAP is more common than Database.

@@ -0,0 +1,251 @@
# Built-in Database Identity Store
JSR 375 mandates that a Java EE container MUST support built-in `IdentityStore` backed by a database.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to use the LdapIdentityStore provider instead of database, as this will be a more common case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, may be I will try to include LdapIdentityStore one as a seperate example and retain this one as well.


This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.

In this example, following users are defined along with the roles they are in.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "groups" is more accurate than "roles" in this context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

dataSourceLookup="${'jdbc/__default'}", // points to database bundled with Glassfish
callerQuery="#{'select password from caller where name = ?'}",
groupsQuery="select group_name from caller_groups where caller_name = ?",
hashAlgorithm = PlaintextPasswordHash.class,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use PlaintextPasswordHash -- we don't want to even suggest that someone could do this. If we put it out there as an example, it will inevitably be included in at least some applications, and it's a huge security hole. The issue is moot if we use LdapIdentityStore. If we stay with this, we should make at least some minimal attempt to do hashing, but a "simple" hash might also be the wrong thing to do, because it may also be insecure, but will fool people into thinking they're doing secure password hashing. Password hashing is hard to get right on your own, which is the entire reason for having the Pbkdf2PasswordHash -- better to use that, unless we're going to put the effort into implementing some other secure password hash algorithm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will replace PlaintextPasswordHash with Pbkdf2PasswordHash. I will try to include LdapIdentityStore as a separate example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Database example has been modified to use Pbkdf2PasswordHash. If time permits I will try to add an example with LdapIdentityStore.

callerQuery="#{'select password from caller where name = ?'}",
groupsQuery="select group_name from caller_groups where caller_name = ?",
hashAlgorithm = PlaintextPasswordHash.class,
hashAlgorithmParameters = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These parameters are meaningless, and therefore may be more likely to confuse than educate. If you want to have parameters, you should supply a PasswordHash impl that will actually use them. If you write your own, you should include an initialize() method that processes any parameters that you show.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will modify accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pbkdf2PasswordHash is being used, these parameters have been replace now:

public String[] getDyna() {
         return new String[]{"Pbkdf2PasswordHash.Algorithm=PBKDF2WithHmacSHA512", "Pbkdf2PasswordHash.SaltSizeBytes=64"};
     }

// and the container will actually handle the login after we return from
// this method.
return httpMessageContext.notifyContainerAboutLogin(
result.getCallerPrincipal(), result.getCallerGroups());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps use result.getCallerPrincipal().getName(), which will demonstrate that the caller name can be passed as a string. I hope that passing CallerPrincipal as an argument does not become a pattern, because CallerPrincipal, ultimately, is not the platform caller principal in GF, and likely won't be on other platforms either. It is also not an "interesting" application caller principal, because it adds no value for an application. It carries nothing but a name. So it ends up as an extra principal carried around by the subject, but adding no value, and is passed here only because it happens to be returned by IdentityStoreHandler.

This is an area where I think the spec could have used more work to clarify the purpose and use of CallerPrincipal; unfortunately we ran out of time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to BasicAuthenticationMechanism, got addressed as part of that.

private IdentityStoreHandler identityStoreHandler;

@Override
public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use the BasicAuthenticationMechanism instead, for this example? It will invoke any configured identity store.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Will modify accordingly.


```java
return httpMessageContext.notifyContainerAboutLogin(
result.getCallerPrincipal(), result.getCallerGroups());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment to above -- use result.getCallerPrincipal().getName()? It's probably reasonable to just use result.getCallerPrincipal() sometimes; we should show both methods in the various examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I will keep that in mind while adding examples in glassfish-samples. for tutorial-examples, I will change it to getName().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you suggested, I will be using BasicAuthenticationMechanism for this example, hence this too will get addressed as part of that.

<dependency>
<groupId>javax.security.enterprise</groupId>
<artifactId>javax.security.enterprise-api</artifactId>
<version>1.0-b11</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version 1.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update it to 1.0.

* bundled with the application.
*/
@RequestScoped
public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use BasicAuthenticationMechanism instead, for this example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will change it accordingly.


public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {

if (usernamePasswordCredential.compareTo("reza", "secret1")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that this is for illustrative purposes only, and that a real IdentityStore should include secure storage and credential validation capabilities? This example is so trivial that it's obviously not usable, but we don't want to encourage the use of hard-coded/in-memory stores, or user databases trivially provided as unencrypted files, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I will add the comment as suggested.

Copy link

@bbuerkle bbuerkle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Vinay - I edited the readme's for both examples.


To support this mandatory requirement, `DatabaseIdentityStore` comes bundled with Glassfish-RI.

This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to: This example demonstrates how you can configure a "DatabaseIdentityStore" to point to a backend database and then use it as an "IdentityStore."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.

In this example, following users are defined along with the roles they are in.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example, "the" following users are defined, along with the roles they are in. (add the and comma)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

|alex|secret2|foo,bar|
|arjan|secret2|foo|
|werner|secret2|foo|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not use real names here. It is best to use something more generic like Joe, Sam, Tom, Sue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

|arjan|secret2|foo|
|werner|secret2|foo|

When a request is made to the application with certain credentials, the authentication mechanism bundled with this application comes into affect and an authentication is done against the `DatabaseIdentityStore` as defined in the application.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...the authentication mechanism bundled with the application comes into effect and authentication is performed against the ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


When a request is made to the application with certain credentials, the authentication mechanism bundled with this application comes into affect and an authentication is done against the `DatabaseIdentityStore` as defined in the application.

Post authentication, the application will also verify the roles the caller is in and will send the details as part of the response.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post authentication, the application also verifies the roles the caller is in and sends the details as part of the response.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

```java
@DeclareRoles({ "foo", "bar", "kaz" })
```
In Glassfish 5.0, role to group mapping is enabled by default. Hence there is no need to bundle `web.xml` with the application to provide mapping between roles and the groups in Glassfish.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In GlassFish 5.0, role to group mapping is enabled by default. Therefore, you do not need to bundle web.xml with the application to provide mapping between roles and groups.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return httpMessageContext.responseUnauthorized();
```

When a request is made to the application, the roles the user is in, gets returned as part of the repsonse.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...the roles the user is in get returned as part of the response.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is going to be replaced completely with BasicAuthenticationMechanism as noted above.


}
```
Notice that, the container itself needs to be made aware of the supported roles and it is done with the help of `@DeclareRoles` annotation as shown above.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the container needs to be made aware of the supported roles, which is achieved with the help of the '@DeclareRoles' annotation as shown above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

```
In Glassfish 5.0, role to group mapping is enabled by default. Hence there is no need to bundle `web.xml` with the application to provide mapping between roles and the groups in Glassfish.

In this example, we would be using credentials of user `reza` to make a request and see if response is according to credentails as specified in `TestIdentityStore` above.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example, we are using the credentials of user 'reza' to make a request and to validate the response according to the credentials specified in 'TestIdentityStore' above.
or
In this example, we are using the credentials of user 'reza' to make a request and to determine if the response is consistent with the credentials specified in 'TestIdentityStore' above.

Not sure which one is technically correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The former one, have replaced accordingly.


`asadmin deploy <project>/target/custom-identity-store.war`

Post which, a request can be made to the application using the URL shown below:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the application is deployed, we can make a request to the application using the URL shown below:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

@vinayvishal vinayvishal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bbuerkle , I have incorporated most of the comments in README, please feel free to modify the contents if you still find any grammatical errors.

@wmhopkins , I will try to include LdapIdentityStore as a separate example. I will update the examples to incorporate your comments and will push the changes to PR.

# Built-in Database Identity Store
JSR 375 mandates that a Java EE container MUST support built-in `IdentityStore` backed by a database.

To support this mandatory requirement, `DatabaseIdentityStore` comes bundled with Glassfish-RI.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


To support this mandatory requirement, `DatabaseIdentityStore` comes bundled with Glassfish-RI.

This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.

In this example, following users are defined along with the roles they are in.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


This example demonstrates how a `DatabaseIdentityStore` can be configured to point to a backend database and how it can then be used as an `IdentityStore`.

In this example, following users are defined along with the roles they are in.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

|alex|secret2|foo,bar|
|arjan|secret2|foo|
|werner|secret2|foo|

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

```
In Glassfish 5.0, role to group mapping is enabled by default. Hence there is no need to bundle `web.xml` with the application to provide mapping between roles and the groups in Glassfish.

In this example, we would be using credentials of user `reza` to make a request and see if response is according to credentails as specified in `TestIdentityStore` above.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The former one, have replaced accordingly.


`asadmin deploy <project>/target/custom-identity-store.war`

Post which, a request can be made to the application using the URL shown below:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

<dependency>
<groupId>javax.security.enterprise</groupId>
<artifactId>javax.security.enterprise-api</artifactId>
<version>1.0-b11</version>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update it to 1.0.

* bundled with the application.
*/
@RequestScoped
public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will change it accordingly.


public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {

if (usernamePasswordCredential.compareTo("reza", "secret1")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I will add the comment as suggested.

@vinayvishal
Copy link
Contributor Author

Being replaced by #3 .
Closing this one due to merge issues.

@vinayvishal vinayvishal deleted the javaee-security-examples branch September 20, 2017 12:02
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.