-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Authorization code issue #281
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d137e91
Add overriding PhysicalNamingStrategy with caseInsensitive false
nivemaham 8fa8d0a
Add custom ApprovalStore with queries with escape characters for uppe…
nivemaham 85b336f
add authorization-code instead of client-credentials to dashboard
nivemaham ff3d467
add custom approval store if the database is recognized as POSTGRES a…
nivemaham 23c698c
add custom approval store if the database is recognized as POSTGRES a…
nivemaham 9d56000
improvements
nivemaham c3c37f3
small code improvements
nivemaham File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/main/java/org/radarcns/management/hibernate/CaseSensitivePhysicalNamingStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.radarcns.management.hibernate; | ||
|
||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; | ||
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; | ||
|
||
public class CaseSensitivePhysicalNamingStrategy extends SpringPhysicalNamingStrategy { | ||
|
||
@Override | ||
protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) { | ||
return false; | ||
} | ||
} |
222 changes: 222 additions & 0 deletions
222
src/main/java/org/radarcns/management/security/PostgresApprovalStore.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* | ||
* Copyright 2012-2013 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.radarcns.management.security; | ||
|
||
import static org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus.APPROVED; | ||
|
||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.sql.Timestamp; | ||
import java.util.Collection; | ||
import java.util.Date; | ||
import java.util.List; | ||
import javax.sql.DataSource; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.dao.DataAccessException; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.core.RowMapper; | ||
import org.springframework.security.oauth2.provider.approval.Approval; | ||
import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; | ||
import org.springframework.security.oauth2.provider.approval.ApprovalStore; | ||
import org.springframework.util.Assert; | ||
|
||
/** | ||
* This class will be used to execute functions related to token approval. It is an duplicate of | ||
* JdbcApprovalStore with escaped case sensitive fields to query. | ||
* | ||
* @author Dave Syer | ||
* @modifiedBy Nivethika | ||
*/ | ||
public class PostgresApprovalStore implements ApprovalStore { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
|
||
private final Logger logger = LoggerFactory.getLogger(PostgresApprovalStore.class); | ||
|
||
private final RowMapper<Approval> rowMapper = new AuthorizationRowMapper(); | ||
|
||
private static final String TABLE_NAME = "oauth_approvals"; | ||
|
||
private static final String FIELDS = | ||
"\"expiresAt\", \"status\",\"lastModifiedAt\",\"userId\"," + "\"clientId\"," | ||
+ "\"scope\""; | ||
|
||
private static final String WHERE_KEY = "where \"userId\"=? and \"clientId\"=?"; | ||
|
||
private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and \"scope\"=?"; | ||
|
||
private static final String AND_LESS_THAN_EXPIRE_AT = " and \"expiresAt\" <= ?"; | ||
|
||
private static final String DEFAULT_ADD_APPROVAL_STATEMENT = | ||
String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, FIELDS); | ||
|
||
private static final String DEFAULT_REFRESH_APPROVAL_STATEMENT = String.format( | ||
"update %s set \"expiresAt\"=?, \"status\"=?, \"lastModifiedAt\"=? " | ||
+ WHERE_KEY_AND_SCOPE, TABLE_NAME); | ||
|
||
private static final String DEFAULT_GET_APPROVAL_SQL = | ||
String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); | ||
|
||
private static final String DEFAULT_DELETE_APPROVAL_SQL = | ||
String.format("delete from %s " + WHERE_KEY_AND_SCOPE + AND_LESS_THAN_EXPIRE_AT, | ||
TABLE_NAME); | ||
|
||
private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = | ||
String.format("update %s set " + "\"expiresAt\" = ? " | ||
+ WHERE_KEY_AND_SCOPE, TABLE_NAME); | ||
|
||
private String addApprovalStatement = DEFAULT_ADD_APPROVAL_STATEMENT; | ||
|
||
private String refreshApprovalStatement = DEFAULT_REFRESH_APPROVAL_STATEMENT; | ||
|
||
private String findApprovalStatement = DEFAULT_GET_APPROVAL_SQL; | ||
|
||
private String deleteApprovalStatment = DEFAULT_DELETE_APPROVAL_SQL; | ||
|
||
private String expireApprovalStatement = DEFAULT_EXPIRE_APPROVAL_STATEMENT; | ||
|
||
private boolean handleRevocationsAsExpiry = false; | ||
|
||
public PostgresApprovalStore(DataSource dataSource) { | ||
Assert.notNull(dataSource); | ||
this.jdbcTemplate = new JdbcTemplate(dataSource); | ||
} | ||
|
||
public void setHandleRevocationsAsExpiry(boolean handleRevocationsAsExpiry) { | ||
this.handleRevocationsAsExpiry = handleRevocationsAsExpiry; | ||
} | ||
|
||
public void setAddApprovalStatement(String addApprovalStatement) { | ||
this.addApprovalStatement = addApprovalStatement; | ||
} | ||
|
||
public void setFindApprovalStatement(String findApprovalStatement) { | ||
this.findApprovalStatement = findApprovalStatement; | ||
} | ||
|
||
public void setDeleteApprovalStatment(String deleteApprovalStatment) { | ||
this.deleteApprovalStatment = deleteApprovalStatment; | ||
} | ||
|
||
public void setExpireApprovalStatement(String expireApprovalStatement) { | ||
this.expireApprovalStatement = expireApprovalStatement; | ||
} | ||
|
||
public void setRefreshApprovalStatement(String refreshApprovalStatement) { | ||
this.refreshApprovalStatement = refreshApprovalStatement; | ||
} | ||
|
||
@Override | ||
public boolean addApprovals(final Collection<Approval> approvals) { | ||
logger.debug(String.format("adding approvals: [%s]", approvals)); | ||
boolean success = true; | ||
for (Approval approval : approvals) { | ||
if (!updateApproval(refreshApprovalStatement, approval) && !updateApproval( | ||
addApprovalStatement, approval)) { | ||
success = false; | ||
} | ||
} | ||
return success; | ||
} | ||
|
||
@Override | ||
public boolean revokeApprovals(Collection<Approval> approvals) { | ||
logger.debug(String.format("Revoking approvals: [%s]", approvals)); | ||
boolean success = true; | ||
for (final Approval approval : approvals) { | ||
if (handleRevocationsAsExpiry) { | ||
int refreshed = jdbcTemplate | ||
.update(expireApprovalStatement, (ps) -> { | ||
ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); | ||
ps.setString(2, approval.getUserId()); | ||
ps.setString(3, approval.getClientId()); | ||
ps.setString(4, approval.getScope()); | ||
}); | ||
if (refreshed != 1) { | ||
success = false; | ||
} | ||
} else { | ||
int refreshed = jdbcTemplate | ||
.update(deleteApprovalStatment, (ps) -> { | ||
ps.setString(1, approval.getUserId()); | ||
ps.setString(2, approval.getClientId()); | ||
ps.setString(3, approval.getScope()); | ||
}); | ||
if (refreshed != 1) { | ||
success = false; | ||
} | ||
} | ||
} | ||
return success; | ||
} | ||
|
||
/** | ||
* Purges expired approvals from database. | ||
* @return {@code true} if removed successfully, {@code false} otherwise. | ||
*/ | ||
public boolean purgeExpiredApprovals() { | ||
logger.debug("Purging expired approvals from database"); | ||
try { | ||
int deleted = jdbcTemplate.update(deleteApprovalStatment, (ps) -> { | ||
ps.setTimestamp(1, new Timestamp(new Date().getTime())); | ||
}); | ||
logger.debug(deleted + " expired approvals deleted"); | ||
} catch (DataAccessException ex) { | ||
logger.error("Error purging expired approvals", ex); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
@Override | ||
public List<Approval> getApprovals(String userName, String clientId) { | ||
logger.debug("Finding approvals for userName {} and cliendId {}", userName, clientId); | ||
return jdbcTemplate.query(findApprovalStatement, rowMapper, userName, clientId); | ||
} | ||
|
||
private boolean updateApproval(final String sql, final Approval approval) { | ||
logger.debug(String.format("refreshing approval: [%s]", approval)); | ||
int refreshed = jdbcTemplate.update(sql, (ps) -> { | ||
ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); | ||
ps.setString(2, (approval.getStatus() == null ? APPROVED | ||
: approval.getStatus()).toString()); | ||
ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); | ||
ps.setString(4, approval.getUserId()); | ||
ps.setString(5, approval.getClientId()); | ||
ps.setString(6, approval.getScope()); | ||
}); | ||
return refreshed == 1; | ||
} | ||
|
||
private static class AuthorizationRowMapper implements RowMapper<Approval> { | ||
|
||
@Override | ||
public Approval mapRow(ResultSet rs, int rowNum) throws SQLException { | ||
String userName = rs.getString(4); | ||
String clientId = rs.getString(5); | ||
String scope = rs.getString(6); | ||
Date expiresAt = rs.getTimestamp(1); | ||
String status = rs.getString(2); | ||
Date lastUpdatedAt = rs.getTimestamp(3); | ||
|
||
return new Approval(userName, clientId, scope, expiresAt, | ||
ApprovalStatus.valueOf(status), lastUpdatedAt); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the new ApprovalStore also works for H2, perhaps rename it to
SanitizedJdbcApprovalStore
And remove this if/else branch?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't. That's why the if else was added later on. H2 doesn't like quotes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's unfortunate... Would using hibernate solve that? Or would that be too large of a refactor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My guess would be not large. Currently, we do not have entities maintained by hibernate in for
oauth
related tables or in other words, we only have the database schema given by spring added. The rest are handled byspring-security-oauth
. I assume having a local entity shouldn't effect the rest. Maybe a separate PR would be better.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, a separate PR seems fine.