Coder Social home page Coder Social logo

apis's Introduction

WARNING: This project is no longer actively maintained.
If anyone is still using this and is willing to take over maintenance, please let us know and we can see how to arrange access. [email protected] [email protected]

APIs

The apis (APIs Secure) project offers an OAuth 2.0 Authorization Server that can be used to kickstart your API authentication. In essence it enables you to focus on your actual resource endpoints and use the out-of-the-box authorization server to authenticate resource owners and subsequently validate the access tokens that were granted to the Client applications. We will describe the typical use cases in more details in sections below.

Features

  • An OAuth2 Authorization Server compliant with the draft v2-31 specification

    • Pluggable authentication and userConsent handling (with default implementations provided)
    • Support for authorization code, implicit grant and client credentials
    • Optional refresh tokens
    • Implementation of a Java Filter to be used in Resource Servers for all required communication with the Authorization Server
    • GUI included for the registration of Resource Servers and Client apps
    • Clients are highly configurable (refresh tokens, allow implicit grant, allow client crendentials etc.)
  • Two OAuth2 demo Resource Servers

    • DropWizard stand-alone Resource Server with limited functionality (using in-memory JSON-based backend) to demo the OAuth Authorization Server
    • Standard Java web application to showcase the use of the communication between typical Resource Servers and the Authorization Server
  • An example Client App implementation to demo the OAuth flow for a typical (possibly native) Client App

    • This 'involves' a running (example) Resource Server and the Authorization Server
  • An implementation add-on for connecting to a compliant SAML IdP for authentication

Getting Started

First clone this repo. To build the sources you need to have maven 3 installed.

The default JVM size is not sufficient - it rarely is - so when running the various modules in test mode using mvn you will have to allocate more memory to the JVM:

export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=512M"

After the clone build the entire project

mvn clean install

Upgrades

Changes between versions are listed in CHANGES.md

Run Authorization Serve.

Go the authorization-server-war and start the application

cd apis-authorization-server-war
mvn jetty:run

The authorization-server-war application is capable of authenticating Resource Owners (e.g. users) and granting and validating Access Tokens (and optional Refresh Tokens) on behalf of Resource Servers that are receiving resource calls from a Client app. It also offers a JavaScript application to manage Resource Servers and Client application instances.

Run Example Resource Server (war & standalone modus)

We have provided two example resource servers. One (apis-example-resource-server-war) is a very simple Java web application that only demonstrates how a Resource Server can communicate with the Authorization Server using the org.surfnet.oaaas.auth.AuthorizationServerFilter (which is a simple javax.servlet.Filter). The AuthorizationServerFilter only protects a single JSP page in the apis-example-resource-server-war module. See the [README of this submodule] (https://github.com/OpenConextApps/apis/tree/master/apis-example-resource-server-war) on how to use curl to test this 'flavor'.

For now we will continue to use the other example resource server (apis-example-resource-server, NOT the apis-example-resource-server-war!) , built using [Dropwizard] (http://dropwizard.codahale.com/), to demonstrate the apis Authorization Server. We will need to start the apis-exampl e-resource-server to demonstrate the entire flow (new Terminal session):

cd apis-example-resource-server
java -jar target/apis-example-resource-server-1.1.1-SNAPSHOT.jar

If the last command gives you an error check if the master version is still 1.1.1-SNAPSHOT.

Run Example Client App

We have now an Authorization Server running and an example Resource Server (and we have not much to show for it, yet!). To demonstrate the entire flow we will start an example Client Application which will communicate with:

  • first the Authorization Server to obtain an Access Token
    • Note that this only works because we have configured both the example-resource-server and the example-client-app in the dummy data defined in /apis-authorization-server/src/main/resources/db/migration/hsqldb/V1__auth-server-admin.sql
  • then the example Resource Server to make an REST API call using the obtained OAuth Access Token
    • Note that the example Resource Server communicates with the Authorization Server to validate the token

Start the example-client-app (new Terminal session)

cd apis-example-client-app
mvn jetty:run

Now start your browser and go to http://localhost:8084/test. In three steps you can see what the client app has to do to make a REST call to example Resource Server. You can also very easily test this against any Resource Server (or for that case an Authorization Server running not running on local host) by changing the values in the client.apis.properties file.

Resource Servers and Client apps GUI registration

The GUI for Resource Servers and Client apps registration can be found at http://localhost:8080/client/client.html:

For an overview of the different roles and the subsequent documentation please refer to the latest version of the oauth v2 specification.

With the client you can create your own Resource Servers and Client applications. The admin client is actually an implicit-grant JavaScript OAuth client that uses the Authorization Server to obtain an access-token and subsequently used the Resource Server endpoints - included in the Authorization server - to manage the data.

screenshot

To login on the client the default authentication module - this is pluggable - is used: a Form based login which will accept anything (see FormLoginAuthenticator#processForm):

private void processForm(final HttpServletRequest request) {
  /*
   * Hook for actually validating the username/ password against a database,
   * ldap, external webservice or whatever to perform authentication
   */
  setAuthStateValue(request, request.getParameter(AUTH_STATE));
  setPrincipal(request, new AuthenticatedPrincipal(request.getParameter("username")));
}

After the login you will need to grant consent (the Authorization Server GUI is actually an OAuth2.0 Client as we are eating our own dogfood) in order for the client to access your personal resources (which you don't have for now but this is going to change).

After this you can add your own ResourceServer and Client instances. See the tooltip's in the insert/ edit forms for more information about the attributes of Resource Servers and Clients.

Admin privileges

It is possible to have admin privileges in the JS GUI, meaning you can edit / delete all of the known Resource Servers and Clients. A common usecase if you have a department responsible for the administration of ResourceServers and Clients. In order to obtain admin rights your AuthenticatedPrincipal needs to return true for the isAdminPrincipal method. The default implementation does not so and everyone can only edit / delete their own ResourceServers and Clients. You can change this by changing the authenticatorClass configuration in the apis-authorization-server-war/src/test/resources/apis.application.properties file to org.surfnet.oaaas.noop.NoopAdminAuthenticator.

The surfconext authn submodule is another production-ready implementation that uses group membership to determine the is-admin feature.

Component overview

The following diagram shows all components and how they play together.

Deployment overview

The authorization server is capable of handing out access tokens on behalf of the user (e.g. the resource owner) for registered Client applications. It uses a database but which flavor you want to use is up to you. We have been developing with mysql and for testing purposes we use the hsqldb file database.

Once a Client app has obtained an access token (in combination with a refresh token if you have configured this for the Client app) it can query the resource server with whatever data you would like to share on behalf of the user (so we have made the implicit assumption that the resource server will only hand out data that is for the users eyes only or perhaps only for users that share a certain membership - the enforcement of that is of course the responsibility of the resource server). Note that the actual authentication of the user is pluggable and in real life the API provided by the resource server and subsequent data will 'know' of the identity returned by the authentication part of the authorization.

When the Client app queries the API of the resource server it will - prior to returning the data - ask the authorization server to validate the access token (For more info see the section How do Resource Servers verify the Access Token?). If the token is valid (e.g. not expired and belonging to the Resource Server and Client app) then the identity of the owner who has granted consent/ access is returned. Note that the actual information in the identity (group memberships, emails or whatever) returned to the resource server is the exact information that was returned by the authentication module when the user proved he could authenticate him/herself.

Client apps and resource servers are registered using the OAuth admin application that is part of the authorization server. Note that the JavaScript OAuth admin application is actually also a Client app which needs to be registered out-of-band (e.g. by SQL) otherwise you will have the chicken-egg paradigm to solve. The resource server is something you will want to provide for yourself. After registration of your resource server with the admin client the key / secret for secure communication with the authorization server are provided to you.

Typically you will want to deploy the authorization server in a servlet container like Tomcat or Jetty. You can of course also deploy the war on an Application Server if you like added complexity. One authorization server can serve up to many, many resource servers and as the communication between authorization server and resource server is a very simple REST / JSON API the technical nature of the resource server really does not care. See the AuthorizationServerFilter.java in the apis-resource-server-library module for an example on how to resource servers can 'talk' to the authorization server.

Extending the defaults

The defaults are alright for getting started, but in real life you must provide at least one implementation (and most likely two):

  • Authentication
    • The default authentication module is very lenient accepting every username/ password combination.
  • UserConsent
    • The default user consent module will probably be sufficient, but most likely you'll want to change the L&F

The default implementations reside in the apis-authorization-server-war submodule.

Authentication module

To change the authentication of Resource Owners that are redirected to the /authorize page you will either extend org.surfnet.oaaas.authentication.FormLoginAuthenticator and override processForm:

/**
 * 
 * Hook for actually validating the username/ password against a database,
 * ldap, external webservice or whatever to perform authentication
 * 
 * @param request
 *          the {@link HttpServletRequest}
 */
protected void processForm(final HttpServletRequest request) {
  setAuthStateValue(request, request.getParameter(AUTH_STATE));
  setPrincipal(request, new AuthenticatedPrincipal(request.getParameter("username")));
}

Or you can implement your own 'org.surfnet.oaaas.auth.AbstractAuthenticator'. The AbstractAuthenticator is a plain javax.servlet.Filter implementation, so it possible to redirect to an entirely different application to perform the authentication.

For an example of an AbstractAuthenticator that uses a federation of SAML2 compliant Identity Providers to perform the actual authentication have a look at SAMLAuthenticator in the submodule apis-surfconext-authn.

User Consent

The default User Consent page is handled by org.surfnet.oaaas.consent.FormUserConsentHandler. You can easily extend and override the default behavior:

/**
 * 
 * Return the path to the User Consent page. Subclasses can use this hook by
 * providing a custom html/jsp.
 * 
 * @return the path to the User Consent page
 */
protected String getUserConsentUrl() {
  return "/WEB-INF/jsp/userconsent.jsp";
}

How do Resource Servers verify the Access Token?

They don't. They ask the Authorization Server to do this. For Java implemented Resource Servers you can use (or extend) the AuthorizationServerFilter in the apis-resource-server-library module. For non-Java Resource Servers the protocol is simple:

GET https://<domain-name-authorization-server>/v1/tokeninfo?access_token=<access_token>
Authorization: Basic <Base64 encoded key:secret >
Accept: application/json

The key/secret are obtained when creating the Resource Server in the admin GUI of the Authorization Server.

The Response is the json representation of the tokenInfo with the client name, the Principal information and the expiry time (if set for this client).

{
    "audience": "Authorization Server Admin Client",
    "scopes": [
        "read",
        "write"
    ],
    "principal": {
        "name": "aaaaa",
        "roles": [],
        "groups": [],
        "adminPrincipal": false,
        "attributes": {
            "DISPLAY_NAME": "test-user",
            "IDENTITY_PROVIDER": "http://mock-idp"
        }
    },
    "expires_in": 1373178401833
}

Default we omit the type-information in the JSON as it would tie the Resource Server to the libraries used in the Authorization Server. For those Resource Servers that depend on a specific subtype of AuthenticatedPrincipal (e.g. would like to cast the principal to a known implementation) it is possible to override the default behaviour by changing the property adminService.jsonTypeInfoIncluded in the properties file that drive the Authorization Server (apis.application.properties) and respectively the properties file that drive the Resource Server (the property file driving the AuthorizationServletFilter - if used - is set using a servlet init-parameter named apis-resource-server.properties.file).

Authorization Server - Resource Server demo flow

First start up the Authorization Server (if you have not already done so):

cd apis-authorization-server-war
mvn jetty:run

When started up in local development mode with Jetty the content of the in-memory test database is populated with the content from apis/apis-authorization-server-war/src/main/resources/db/migration/hsqldb_content/V1__auth-server-admin.sql. One entry in that file is a client configured with allowedClientCredentials=true.

/*
Client for client credentials
*/
INSERT INTO client (id, contactEmail, contactName, description,
                    clientName, thumbNailUrl, resourceserver_id,
                    clientId, secret, allowedClientCredentials)
VALUES
    (99993, '[email protected]',
    'john.client.credential.grant', 'it test client credential grant',
    'it test client credential grant', 'thumbnailurl', 99997,
    'it-test-client-credential-grant', 'some-secret-client-credential-grant', 1);
INSERT INTO Client_scopes values (99993, 'read');

Let's test this client with curl. We need the base64 encoded client_key:secret (it-test-client-credential-grant:some-secret-client-credential-grant):

echo -n 'it-test-client-credential-grant:some-secret-client-credential-grant' | openssl base64

and we use this to - client credential grant does not involve any user involvement as it is granted to highly trusted clients - obtain a access token:

curl -v -H "Accept: application/json" -H "Content-type: application/x-www-form-urlencoded" -H \
  "Authorization: Basic aXQtdGVzdC1jbGllbnQtY3JlZGVudGlhbC1ncmFudDpzb21lLXNlY3JldC1jbGllbnQtY3JlZGVudGlhbC1ncmFudA==" \
  -X POST -d 'grant_type=client_credentials' http://localhost:8080/oauth2/token

The result is a new access token:

{
    "scope": "read",
    "access_token": "38b0b9e5-0ff0-42f9-a9df-28cfaf996de2",
    "token_type": "bearer",
    "expires_in": 0
}

Now test the call that a Resource Server would make to the Authorization Server when this client uses his newly obtained access token to perform an API call against the Resource Server. We will mimic the Resource Server that actually is connected to the client we used (id = 99997, key:secret is it-test-resource-server:somesecret).

This is the call - proprietary API as described out-of-scope in the OAuth2 specification - to the Authorization Server to validate the access token:

curl -v -H "Authorization: Basic aXQtdGVzdC1yZXNvdXJjZS1zZXJ2ZXI6c29tZXNlY3JldA==" \
  "http://localhost:8080/v1/tokeninfo?access_token=38b0b9e5-0ff0-42f9-a9df-28cfaf996de2"

And the result as expected (note as we used client credential flow the principal name is the client name);

{
    "audience": "it test client credential grant",
    "scopes": [
        "read"
    ],
    "principal": {
        "name": "it-test-client-credential-grant",
        "roles": [],
        "groups": [],
        "adminPrincipal": false,
        "attributes": {}
    },
    "expires_in": 0
}

If you write your own implementation of the above flow for your Resource Servers strongly consider caching subsequent calls & answers from the Authorization Server.

Plugging in your custom implementations

The Authorization Server is wired up using a Spring configuration. The class org.surfnet.oaaas.config.SpringConfiguration in the apis-authorization-server-war module is responsible for wiring up the dependencies. You don't need to override this configuration if you only want to change the authentication (and/ or the user consent) as we have externalized this into the apis.application.properties file. The authorization server which you have started up with the maven jetty plugin uses the apis.application.properties file in apis-authorization-server-war/src/test/resources.

In real life deployment you will need to provide the authorization server with an external apis.application.properties file. We have not put this into the war file as you would end up with an environment specific war application.The apis.application.properties file contains all environment specific variables like database settings and the authentication implementation:

# The authentication module
authenticatorClass=org.surfnet.oaaas.authentication.FormLoginAuthenticator

# The user consent module
userConsentHandlerClass=org.surfnet.oaaas.consent.FormUserConsentHandler

If you would prefer a different approach you can override the org.surfnet.oaaas.config.SpringConfiguration and implement your own logic to wire your Authentication implementation:

/**
 * Returns the {@link AbstractAuthenticator} that is responsible for the
 * authentication of Resource Owners.
 * 
 * @return an {@link AbstractAuthenticator}
 */
@Bean
public AbstractAuthenticator authenticator() {
  return (AbstractAuthenticator) getConfiguredBean("authenticatorClass");
}

The REST interface to build your own GUI

You can use the exposed REST interface of the ResourceServerResource, ClientResource and AccessTokenResource to build your own GUI. The resources offer full CRUD for the persistent objects. See the annotations on the mentioned Resources.

While we were working on the JavaScript Admin client included in the Authorization Server war we locally disabled the login and consent to speed up the local feedback cycle when developing in 'jetty-modus':

# The authentication module
# authenticatorClass=org.surfnet.oaaas.authentication.FormLoginAuthenticator
authenticatorClass=org.surfnet.oaaas.noop.NoopAuthenticator

# The user consent module
# userConsentHandlerClass=org.surfnet.oaaas.consent.FormUserConsentHandler
userConsentHandlerClass=org.surfnet.oaaas.noop.NoopUserConsentHandler

SURFConext Authn Authenticator

See the information in the surfconext authn submodule for detailed information on the SURFconext SAML Authentication implementation.

SSL/TLS

As noted in the OAuth 2.0 RFC (1, 2, 3), the use of TLS is required, as credentials are transmitted in clear-text. This is not enforced at code level, but it must be when deploying the application.

Tests

You can build the entire project including the integration and selenium tests (which are dependent on your version of FireFox):

mvn clean install -P integration

apis's People

Contributors

alanvdam avatar alfredsang avatar baszoetekouw avatar biancini avatar deepk2u avatar gilgamez avatar gvanderploeg avatar hanswesterbeek avatar jmsnoeij avatar miken123 avatar oharsta avatar peterrosell avatar praseodym avatar raymondbourges avatar richtera avatar sfitts avatar steven-aerts avatar thijskh avatar tomkuipers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apis's Issues

Error running demo: Out of Memory Error - PermGen space

Tried to work through the demo features, and got as far as the 2nd step in the browser, but am consistently getting an out of memory error. I'm running this on a high spec mac book so it would seem to be a code issue rather than a system issue. Is this something you've seen before?

2013-07-04 20:41:12.203:WARN:oejs.ServletHandler:Error for /mujina-idp/AuthnResponder
java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:792)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:415)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377)
at org.opensaml.common.impl.AbstractSAMLObjectMarshaller.marshall(AbstractSAMLObjectMarshaller.java:57)
at org.opensaml.xml.io.AbstractXMLObjectMarshaller.marshall(AbstractXMLObjectMarshaller.java:86)
at nl.surfnet.mujina.saml.xml.AssertionGenerator.signAssertion(AssertionGenerator.java:117)
at nl.surfnet.mujina.saml.xml.AssertionGenerator.generateAssertion(AssertionGenerator.java:100)
at nl.surfnet.mujina.saml.xml.AuthnResponseGenerator.generateAuthnResponse(AuthnResponseGenerator.java:63)
at nl.surfnet.mujina.saml.SSOSuccessAuthnResponder.handleRequest(SSOSuccessAuthnResponder.java:118)
at org.springframework.web.context.support.HttpRequestHandlerServlet.service(HttpRequestHandlerServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1367)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)

AS redirects to an invalid redirection URI

When requesting the Authorization Code indicating an invalid or otherwise forged redirection URI, a GET request to e.g.
https://apis.example.de/oauth2/authorize?response_type=code&client_id=registered_id&redirect_uri=https://unregisted.client.com/malware.php&scope=myScope&state=12345
redirects to that invalid redirection URI, giving an attacker the code. However, in the preamble of http://tools.ietf.org/html/rfc6749#section-4.1.2.1 it is stated that it "MUST NOT" do this, leaving it a task of the AS to return an error to the user.
This should be considered a security hole, as some attacker can redirect the user to its own page.

Unable to compile

When I try to compile using mvn clean install I get the following exception:

java.lang.NoSuchMethodError: org.springframework.beans.factory.annotation.InjectionMetadata.needsRefresh(Lorg/springframework/beans/factory/annotation/InjectionMetadata;Ljava/lang/Class;)Z at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:368) at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:323) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:844) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:498) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:741) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)

And the report of the maven execution:
[INFO] API Secure ........................................ SUCCESS [0.971s]
[INFO] API Secure - resource server library .............. SUCCESS [9.049s]
[INFO] API Secure - authorization server ................. SUCCESS [14.483s]
[INFO] API Secure - conext authentication plugin ......... SUCCESS [4.320s]
[INFO] API Secure - example resource server .............. SUCCESS [18.038s]
[INFO] API Secure - mock openconext group api ............ SUCCESS [2.018s]
[INFO] API Secure - authorization server webapp .......... FAILURE [7.814s]
[INFO] API Secure - example resource server war .......... SKIPPED
[INFO] API Secure - example client app war ............... SKIPPED
[INFO] API Secure - authorization server webapp dist ..... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 57.281s
[INFO] Finished at: Fri Feb 07 09:30:21 CET 2014
[INFO] Final Memory: 77M/163M

So it seems to me that multiple spring libraries are included. This happens both with the 1.3.3 and 1.3.4 versions. What can I do to make it work?

Thanks!

Unable to add a resource server

I'm trying to work with your server implementation, by the way when I'm trying to add a new resource server, from the page containing the proper form, nothing happens. I just fill the fields and then click on "save changes" but it seems to do nothing. Any idea about this kind of problem?

PS: I'm getting a similar issue when dealing with tokens. If i try to delete one token it opens a pop-up asking for confirmation, but then nothing happens. (i.e. tokens are not deleted)

Could be something related to the java version installed?

Let /v1/tokeninfo return Token Creation Date

Concerning dates, the /v1/tokeninfo endpoint returns a JSON string that only contains the "expires_in" key, with a value that is taken from the database directly without recomputation. Thus a resource server can neither know when the token was created nor when it will expire.
Proposal would be to enhance this to either a) dynamically compute the "expire_in" value such that it correctly reflects the time left from "now", or b) additionally release a "creationdate" key/value pair to be released via /tokeninfo.
Preference is on b) because it adds valueable information, the "creationdate" value can be taken directly from the database and there is no computation of the expiry date needed while accessing /tokeninfo.

AS /admin/resourceServer mixes ResourceServer and Client IDs

I have an RS and a Client, both have an ID of 22222 in the DB (set up in analogy to V1__auth-server-admin.sql). Now when I want e.g. add an additional scope to that RS via the admin client interface (a modification which ends up in a POST to /oauth2/admin/resourceServer/22222), the user agent sees an Internal Server Error, with the Cause in apis.log:

org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Attempted to attach instance "22222" of type "class org.surfnet.oaaas.model.ResourceServer", but this instance is already in the datastore as type "class org.surfnet.oaaas.model.Client".

I believe this is a bug, or otherwise one needs a specification that ID ranges of different classes must be kept apart (a workaround I chose short-term).

Problems with auth server

I'm having some problems in getting tokens from auth server. I'll try to explain here:

Running Authorization Server - Resource Server demo flow:

Using the dummy account for test I'm getting this response after the performing the curl as suggested:

curl -v -H "Accept: application/json" -H "Content-type: application/x-www-form-urlencoded" -H \
  "Authorization: Basic aXQtdGVzdC1jbGllbnQtY3JlZGVudGlhbC1ncmFudDpzb21lLXNlY3JldC1jbGllbnQtY3JlZGVudGlhbC1ncmFudA==" \
  -X POST -d 'grant_type=client_credentials' http://localhost:8080/oauth2/token

I'm getting back this response:

 HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Transfer-Encoding: chunked
* Server Jetty(8.1.4.v20120524) is not blacklisted
< Server: Jetty(8.1.4.v20120524)
< 
{"error":"unsupported_grant_type","error_description":"The supported grant_type values are 'authorization_code' and 'refresh_token'"}* Connection #0 to host localhost left intact

I've tried even by building the http header using a browser-plugin and the result is slightly different:

  1. First it ask me for a username/password (couldn't find a valid pair btw)
  2. Then it returns a 401 unauthorized response.

Something similar happens when I'm trying to get a token by authorization code flow: I'm able to get a request_code but not able to exchange it for an authorization token. When I'm asking by building the http request header via browser plugin it asks me again for the username-login password for connecting to OAuthSecure2 server.

PS: The key that I'm using for generating the key use in Authorization header is obtained by openssl base64 command

Authorization server war doesn't work if not deployed at root.

I've found at least 2 issues so far:

  • The redirect URL in index.html is "/client/client.html" which only works off root.
  • When logging into the client application you end up in an infinite redirect loop processing the token response. Not sure why at this point.

Workaround is to ensure that the WAR is deployed at the root context of the container.

Problematic dependencies in AuthorizationServerFilter

The org.surfnet.oaaas.auth.AuthorizationServerFilter class is meant to be used independently by resource server applications. Based on an initial inspection of the code, however, there are a couple of unpleasant consequences of it being packaged as part of the authorization server codebase.

First, if the apis-authorization-server artifact is included as a dependency in the resource server, it appears that the auth server's JAX-RS resources will be auto-discovered and provisioned in the resource server application.

Second, the filter pulls in heavyweight dependencies on Spring, Guava, SLF4J, and Jackson. The Spring dependency is just a couple of convenience utilities and really shouldn't be included. Guava, SLF4J, and Jackson are easier to deal with as they are common, but these are mostly not required either and could be eliminated.

I realize that the filter code can be copied and the dependencies removed downstream, but ideally, the project could package the filter in a separate submodule that can be referenced independently by resource servers with minimal dependencies.

ClassNotFoundException when started using Java 6 jvm while starting up authorization server in jersey

apis-authorization-server-war does not start when I use Java 6 as my runtime environment. I get the following stack trace when I jetty:run.

java.lang.UnsupportedClassVersionError: nl/surfnet/spring/security/opensaml/ServiceProviderAuthenticationException : Unsupported major.minor version 51.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:415)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.surfnet.oaaas.config.SpringConfiguration.getConfiguredBean(SpringConfiguration.java:150)
at org.surfnet.oaaas.config.SpringConfiguration.authenticator(SpringConfiguration.java:129)
at org.surfnet.oaaas.config.SpringConfiguration$$EnhancerByCGLIB$$5f524ff7.CGLIB$authenticator$2()
at org.surfnet.oaaas.config.SpringConfiguration$$EnhancerByCGLIB$$5f524ff7$$FastClassByCGLIB$$6a9f3edc.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:286)
at org.surfnet.oaaas.config.SpringConfiguration$$EnhancerByCGLIB$$5f524ff7.authenticator()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:160)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1055)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:951)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:764)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:756)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:242)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1234)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:699)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:256)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:224)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:90)
at org.eclipse.jetty.server.Server.doStart(Server.java:262)
at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:65)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:511)
at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:364)
at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:516)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:106)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:318)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:153)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:555)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:414)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:357)

Exeption occurred when using Tomcat container

org.springframework.dao.InvalidDataAccessApiUsageException: Result type "class org.surfnet.oaaas.model.AccessToken" does not have any public fields or setter methods for the projection or aggregate result element "creationDate", nor does it have a generic put(Object,Object) method that can be used, nor does it have a public constructor that takes the types null.; nested exception is <openjpa-2.2.0-r422266:1244990 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Result type "class org.surfnet.oaaas.model.AccessToken" does not have any public fields or setter methods for the projection or aggregate result element "creationDate", nor does it have a generic put(Object,Object) method that can be used, nor does it have a public constructor that takes the types null

Need help regarding verification of access token with authorization server

Hi,

How should one send the following request to the authorization server :

GET https:///v1/tokeninfo?access_token=<access_token>
Authorization: Basic
Accept: application/json

I am replacing the content within <> accordingly to my environment. Further, should I also include Base64 encoded in the authorization section.

I am passing the above request in my browser itself, can you provide me some information on how to send this GET request to the authorization server.

I am still a ametuer with this stuff, please do help me.

With regards,
Prashanth

Purpose of "v1" servlet mapping

I noticed that the server war provides a servlet mapping under three roots:

  • admin -- applies an auth check which requires a previously issued bearer token, so it seems to be designed to protect access to the resource API (for registering resource servers and clients).
  • oauth2 -- applies an authentication check specifically to the authorize resource, so it appears to be designed to handle the RO authentication required by section 3.1 of the spec.
  • v1 -- just provides raw access.

However the code behind the various resources makes assumptions about which filters will actually be applied. For example, the resource manager code (such as ResourceServerResource.java) expects that the access will have been authorized and thus a verified token will be available. This isn't in this case, so the result is an NPE on any access. What is the intended purpose of the v1 mapping?

A related question is why all 3 mappings actually give you access to the same resource URIs (so you could issue "admin/authorize" or "oauth2/resourceServer" as valid URIs, though they may or may not work properly). Seems like a more precise set of mappings would be better to avoid confusion and spurious errors (or accidental success).

Transport dt_socket 8787 already in use

On starting the server as suggested

cd apis-authorization-server-war
mvn jetty:run

the first line of output is

Listening for transport dt_socket at address: 8787

On starting the client as suggested

cd apis-example-client-app
mvn jetty:run

the output is

ERROR: transport error 202: bind failed: Address already in use
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [../../../src/share/back/debugInit.c:690]
FATAL ERROR in native method: JDWP No transports initialized, jvmtiError=AGENT_ERROR_TRANSPORT_INIT(197)
Aborted

My understanding is JVM debugger for server is bounding on port 8787 and the debugger from client is also trying to bound to port 8787 but complains because it is already in use.

I also assume that Jetty automatically starts debugger when tests are configured.

Load balancing Authorization Server

Quick question - If we have multiple instances of auth servers that are behind a load balancer, are there any additional configurations or any issues we should watch out for? We will be using Oracle DB for all persistence.

Missing dependency. Please provide repo details

Hi, I'm missing a dependency called org.surfnet.coin:mujina-idp:war:2.13.0.

Please provide repo details, thanks!

[ERROR] Failed to execute goal org.mortbay.jetty:jetty-maven-plugin:8.1.4.v20120524:run (default-cli) on project apis-authorization-server-war: Execution default-cli of goal org.mortbay.jetty:jetty-maven-plugin:8.1.4.v20120524:run failed: Plugin org.mortbay.jetty:jetty-maven-plugin:8.1.4.v20120524 or one of its dependencies could not be resolved: Could not find artifact org.surfnet.coin:mujina-idp:war:2.13.0 in central (http://repo.maven.apache.org/maven2) -> [Help 1]

When testing the apis-authorization-server-war getting looped page refreshes

When I login it keeps on going back and forth between authorization and the page over and over and never lets me use the logged in pages (/client/client.html)
The log file is filled with:

WARNING: A servlet POST request, to the URI http://localhost:8080/oauth2/authorize, contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
09:12:03.722 [qtp1146625698-19] WARN  o.s.o.auth.AuthorizationServerFilter - No valid access-token on request. Will respond with error response: 403 OAuth2 endpoint
09:12:03.736 [qtp1146625698-24] WARN  o.s.o.auth.AuthorizationServerFilter - No valid access-token on request. Will respond with error response: 403 OAuth2 endpoint

Not sure what to check.

Question about "authorization-server-url"...

I'm a devops engineer, and I'm working on a problem with a deployment of the apis-authorization-server-war. I have no idea whether my developers are using/deploying the WAR as intended, so please excuse me if we are being total hacks. :)

I am currently trying to figure out how to override certain property settings. My developers were originally including an apis.application.properties directly in the apis-authorization-server-war. This worked fine for a single deployment environment, but we need to deploy to multiple environments, and we would like to do so without building multiple wars with different properties files like it is done in the apis-authorization-server-dist.

It appears that most of the properties are used/configured in such a way that they can be overridden with context parameters. In other words, we deploy to both the WAR and an application context file. In the context file, we override the "jdbc.driverClassName" property by including "". Unfortunately, properties like "adminService.tokenVerificationUrl" cannot be overridden in the same way.

After poking around for a while, I realized that could define the various "adminServce" properties in a filter in the web.xml rather than a properties file (using param name "authorization-server-url" in place of "adminService.tokenVerificationUrl" and so forth). I thought that I might then be able to override the properties using the context params, but no such luck. I also experimented with using something like "${authorization-server-url}" as the param variable and then overriding with environment variables. I tried defining the env variables several ways: (1) In the context file -- '', (2) From the command-line, (3) etc; but again with no luck.

It really seems like there should be a good way to easily override these "adminService" properties externally to the WAR, but I'm at a loss. Is there a way? Any help or guidance would be greatly appreciated.

Use server with Android client

I am trying to use the server with Android clients (Native app) not based on webview.

Below is what I understood from the documentation

  1. Resource Servers and Client apps can be registered from the GUI found at http://localhost:8080/client/client.html

selection_002

  1. Pressing "Login" will present a screen like this and your can enter anything into login/password field

selection_001

QUESTION - HOW TO CONFIGURE THIS LOGIN PAGE SO THAT IT DOES NOT USE ANY USER NAME/PASSWORD?

  1. On pressing add another resource the following page is presented

selection_002

QUESTION - I HAVE A JAVA SERVLET BASED RESOURCE SERVER HOSTED ON TOMCAT, HOW TO ADD THAT SERVER ON THIS PAGE?

The client will be native apps on Android devices, how do I register them?

What OSS license are you operating under?

Just a quick question. I didn't see any licensing information associated with this repo. Curious if you intended it to include a license. This will help people understand how they can use this project and the limits on how it can be used.

Thanks!

Exceptions thrown on concurrent bearer token issuance requests

Hello,

Thank you so much for APIs Secure. It's working great, except for one issue that I'm hoping someone might be kind enough to help me out with. It would seem that when several (implicit grant) bearer token issuance requests come in at the same time that one of three exceptions intermittently are thrown.

I'm using a brand new clone of the apis repository with only the following adjustments to: apis-authorization-server-war/src/test/resources/apis.application.properties:

  1. Using MySQL instead of hsqldb.
  2. Using NoopAuthenticator as authenticatorClass.
  3. Using NoopUserConsentHandler as userConsentHandlerClass.

The authorization server is run via (also reproduced under Tomcat 8):

mvn jetty:run

To reproduce the below issue, I'm executing:

for i in seq 1 3; do (curl -i http://$host:8080/oauth2/authorize?response_type=token\&client_id=$client_id\&redirect_uri=http://localhost:$port/redirect\&scope=read\&state=example &); done

After running that a few times, I'll begin seeing the following exceptions:

https://gist.github.com/jsmith190721117/26912e8bd7f0937a35c4#file-gistfile1-txt
https://gist.github.com/jsmith190721117/3cca683e9d69f6c0deeb#file-gistfile1-txt
https://gist.github.com/jsmith190721117/f1dca4ad373a5fc5d9ff#file-gistfile1-txt

Any assistance that anyone could provide would be greatly appreciated. Thank you.

Include all SAML attributes in principle profile

How can I include a flexible set of SAML attributes (e.g. uuid, displayName, eduPersonPrincipleName) in the principle profile. At the moment only DISPLAY_NAME and INDENTITY_PROVIDER show up as attributes in the principle information. See the example taken from the README:

{
    "audience": "Authorization Server Admin Client",
    "scopes": [
        "read",
        "write"
    ],
    "principal": {
        "name": "aaaaa",
        "roles": [],
        "groups": [],
        "adminPrincipal": false,
        "attributes": {
            "DISPLAY_NAME": "test-user",
            "IDENTITY_PROVIDER": "http://mock-idp"
        }
    },
    "expires_in": 1373178401833
}

I noticed the constants IDENTITY_PROVIDER and DISPLAY_NAME in
https://github.com/OpenConextApps/apis/blob/8d5ac4616bd999415129ed1bb1b8e179ca418a26/apis-surfconext-authn/src/main/java/org/surfnet/oaaas/conext/SAMLAuthenticatedPrincipal.java.
How can I pass additional SAML attributes, in particular eduPersonPrincipalName, to the principle attributes?

The use case for this is an API facade tied to backend systems for 'someuniversity' and 'otheruniversity'. Based on the value of eduPersonPrincipleName ([email protected]) / ([email protected]) it is serving resources from 'someuniversity' backend system or 'otheruniversity' backend system.

java.lang.OutOfMemoryError: PermGen space

No matter what MAVEN_OPTS I'm setting:
MAVEN_OPTS="-d64 -Xms3G -Xmx3G -XX:MaxPermSize=2G -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
JAVA_HOME=C:\lib\java\jdk1.7.40
I keep getting this error on sample applications.

Stack trace:
java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:792)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:789)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.util.ResourceBundle$Control.newBundle(ResourceBundle.java:2566)
at java.util.ResourceBundle.loadBundle(ResourceBundle.java:1436)
at java.util.ResourceBundle.findBundle(ResourceBundle.java:1400)
at java.util.ResourceBundle.findBundle(ResourceBundle.java:1354)
at java.util.ResourceBundle.findBundle(ResourceBundle.java:1354)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1296)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:795)
at com.sun.tools.javac.util.JavacMessages.getBundles(JavacMessages.java:121)
at com.sun.tools.javac.util.JavacMessages.setCurrentLocale(JavacMessages.java:73)
at com.sun.tools.javac.util.JavacMessages.(JavacMessages.java:98)
at com.sun.tools.javac.util.JavacMessages.(JavacMessages.java:88)
at com.sun.tools.javac.main.Main.getLocalizedString(Main.java:584)
at com.sun.tools.javac.main.Main.resourceMessage(Main.java:527)
at com.sun.tools.javac.main.Main.compile(Main.java:459)
at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:132)
at org.apache.jasper.compiler.Jsr199JavaCompiler.compile(Jsr199JavaCompiler.java:248)
at org.apache.jasper.compiler.Compiler.generateClass(Compiler.java:384)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:453)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)

Missing Dependencies

I am trying to build the repo that I just cloned and getting the following error:

[ERROR] /E:/github/apis/apis-surfconext-authn/src/main/java/org/surfnet/oaaas/conext/SAMLAuthenticator.java:[39,39] package org.opensaml.ws.message.decoder does not exist

What repository contains the missing dependencies?

Thanks,
Caleb

Every Client app belongs to one resource server?

I'm wondering why you limit clients to access only one resource server?
"Every client app belongs to one (and only one) resource server".

My client must access multiple resource servers with (possibly different) tokens.
Is there any way to extend the data model to a 1-n relation of clients and resource servers?

Btw: Great work, thanks! Your example did run out of the box (except for the jetty-maven PermGen Space issue).

Getting Issue on APIS

Hi,
I am very new to OAuth2 and Maven and hence i am trying to install APIS and while i am running command from command prompt getting below issues

[ERROR] Failed to execute goal org.apache.openjpa:openjpa-maven-plugin:2.2.0:enh
ance (enhancer) on project apis-authorization-server: Execution enhancer of goal
org.apache.openjpa:openjpa-maven-plugin:2.2.0:enhance failed: Plugin org.apache
.openjpa:openjpa-maven-plugin:2.2.0 or one of its dependencies could not be reso
lved: Could not transfer artifact org.slf4j:slf4j-api:jar:1.6.1 from/to central
(https://repo.maven.apache.org/maven2): Connect to repo.maven.apache.org:443 [re
po.maven.apache.org/199.27.79.215] failed: Connection timed out: connect -> [Hel
p 1]

Please guide me to fix the issue .

Question on resource server

I have a basic (newbie) question.

The Resource Server definition (as configured through the UI) does not point to the actual resource server. There is no URL defined for the resource server.
So how can a Client Application be restricted to only access resource of the desired resource server? Should this be custom implementation?

Token expiration not taking effect

Although I can set a token expiration value, it doesn't appear to have any effect. Is there anything implemented for expiration, or is this a bug?

Denying consent gives a 500 error

Login on admin client
view consent page
click 'deny'.

server side log says:
21:01:25.071 [qtp15986263-28] WARN o.s.oaaas.resource.TokenResource - Not a valid AbstractAuthenticator.AUTH_STATE on the Request

java.io.IOException: Illegal footer: -property-named-idpCertificate

Hello,

I am seeing above (java.io.IOException: Illegal footer: -property-named-idpCertificate) when starting apis-authorization-server-war-1.3.6-SNAPSHOT in this environment -

java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

sw_vers
ProductName: Mac OS X
ProductVersion: 10.9.2
BuildVersion: 13C64

bin/catalina.sh version
Using CATALINA_BASE: /Users/naga/ocat
Using CATALINA_HOME: /Users/naga/ocat
Using CATALINA_TMPDIR: /Users/naga/ocat/temp
Using JRE_HOME: /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home
Using CLASSPATH: /Users/naga/ocat/bin/bootstrap.jar:/Users/naga/ocat/bin/tomcat-juli.jar
Server version: Apache Tomcat/7.0.54
Server built: May 19 2014 10:26:15
Server number: 7.0.54.0
OS Name: Mac OS X
OS Version: 10.9.2
Architecture: x86_64
JVM Version: 1.7.0_51-b13
JVM Vendor: Oracle Corporation

Has anyone encountered this issue? If yes, how to overcome?

Thanks
Naga

Problems accessing oauth server (i.e. war) from a remote location using example client

Hello guys,

I am running the apis-authorization-server-war on a ubuntu virtual machine and trying to access the server from my host os which is also ubuntu with the example client.

I can succesfully access the server client html page from my host and also start the authorization process from the example client in the host os.

The problem pops up during the mujina login. I somehow can't access the page from my host os. It defaultly goes to the localhost:8080/mujina-idp/SingleSignOnService. I know that, I should replace the localhost with my server IP address.

So, can you please tell me, what changes that are required to be made in the server files / client files. It would be great, If you can guide me through this process. I am still a ametuer with this stuff.

Cheers !!

Thanking you in advance !!

With regards,
Prashanth

Scopes delimited with comma, but should be space

Unless I misread the spec, section 3.3 says that the list of scopes should be space delimited. However, my read of the code is that it is being treated as a comma delimited list.

It turns out that this is hard to see because what happens is that the space delimited list of scopes just gets treated as a single scope in the code (with the spaces preserved), so in the end it comes out looking correct (it just isn't doing what I think it thinks it is doing).

Authorization Code does not Expire

From http://tools.ietf.org/html/rfc6749#section-4.1.2:
code
REQUIRED. The authorization code generated by the
authorization server. The authorization code MUST expire
shortly after it is issued to mitigate the risk of leaks. A
maximum authorization code lifetime of 10 minutes is
RECOMMENDED. The client MUST NOT use the authorization
code more than once....

From what I saw, even 2 year old authZ codes do still work, so I guess some cleanup process should be implemented.

Token validation endpoint returns burdensome Java type information

Since 3673319 the serialization of VerifyTokenResponse contains Java type information. The following is a representative example from the authorization server webapp:

["org.surfnet.oaaas.model.VerifyTokenResponse",
{
    "audience": "client",
    "scopes": ["org.apache.openjpa.util.java$util$ArrayList$proxy", ["read", "write"]],
    "principal": ["org.surfnet.oaaas.conext.SAMLAuthenticatedPrincipal",
    {
        "name": "admin",
        "roles": ["java.util.ArrayList", []],
        "groups": ["java.util.ArrayList", []],
        "adminPrincipal": false,
        "attributes": ["java.util.HashMap",
        {
            "DISPLAY_NAME": "admin",
            "IDENTITY_PROVIDER": "http://mock-idp"
        }]
    }],
    "expires_in": 0
}]

In order to deserialize such JSON, a resource server must explicitly include at least two additional dependencies (and inherit their numerous transitive dependencies). Otherwise, it will experience errors such as the following:

ERROR [2013-07-02 19:36:14,535] org.surfnet.oaaas.auth.AuthorizationServerFilter: Exception in reading result from AuthorizationServer
! org.codehaus.jackson.map.JsonMappingException: Invalid type id 'org.surfnet.oaaas.conext.SAMLAuthenticatedPrincipal' (for id type 'Id.class'): no such class found (through reference chain: org.surfnet.oaaas.model.VerifyTokenResponse["principal"])

The OpenJPA dependency, although extraneous from the resource server's perspective, can be easily handled by declaring it in apis-resource-server-library/pom.xml.

However, the SAML dependency is indicative of a larger problem, which is that the presence of this type information couples a resource server to the specific authenticators used by the authorization server. That is especially surprising when simply using AuthorizationServerFilter to protect resources.

Question on how login.jsp is invoked

Hi, not sure if this is right place to ask question on the code, but I have not found alternative path to ask it, so here goes.

I am reviewing the code (OpenConextApps/apis) for possible use in a project/demo that I am scoping.

One thing I am stuck on is how login.jsp gets invoked. Basically, I can see how ClientController creates the Authorization Request and sends redirect to authorization server.

I am assuming that FormLoginAuthenticator is configured in apis.application.properties, although in downloaded version it is commented out, but when I set up the project I will uncomment it accordingly.

Now I assume when the redirect is received at the authorization server (war) that AbstractAuthenticator will have doFilter() invoked, and in turn invoke authenticate() in FormLoginAuthenticator.

Here is where I have the problem. it appears to me that the only way that login.jsp can be shown to the user is if FormLoginAuthenticator.processInitial() is called.

However, it appears to me that the only way that this can happen is if the principal is null, which is ok, but first the code must find that request.getMethod().equals("POST") is false!

Unless I am missing something the above should return true, since in ClientController.step2() that the preceding annotation @RequestMapping sets method=RequestMethod.POST.

So, what am I missing? do I have it completely wrong? or does getMethod() return something other than POST?

Any help or suggestion where I might better submit the question would be appreciated.

Thanks,
Rich

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.