Skip to content

Commit

Permalink
Merge pull request #452 from Opetushallitus/OK-326
Browse files Browse the repository at this point in the history
Ok 326
  • Loading branch information
msiukola committed Mar 27, 2024
2 parents 9f663d8 + 88fdff0 commit e904c00
Show file tree
Hide file tree
Showing 16 changed files with 88 additions and 19 deletions.
2 changes: 2 additions & 0 deletions src/main/js/controllers/hakutoiveidenMuokkaus.js
Expand Up @@ -33,6 +33,8 @@ export default ['$scope', '$location', '$http', '$cookies', function($scope, $lo
$scope.loading = false;
$scope.application = new Hakemus(response.data);
$scope.application.oiliJwt = response.oiliJwt;
$scope.application.migriJwt = response.migriJwt;
$scope.application.migriUrl = response.migriUrl;
$scope.application.token = token;
$scope.application.isHakutoiveidenMuokkaus = true;
const henkilotiedot = response.data.hakemus.answers.henkilotiedot;
Expand Down
4 changes: 3 additions & 1 deletion src/main/js/directives/application.html
Expand Up @@ -76,7 +76,9 @@ <h2>{{application.haku.name }}</h2>
</section>

<section class="migri" ng-if="application.showMigriURL()">
<migri migri="application.showMigriURL()">
<migri migri="application.showMigriURL()"
token="{{application.migriJwt}}"
url="{{application.migriUrl}}">
</migri>
</section>

Expand Down
2 changes: 2 additions & 0 deletions src/main/js/directives/applicationList.js
Expand Up @@ -25,6 +25,8 @@ export default ["restResources", function (restResources) {
$scope.applications = _.map(data.applications, function(json) {
var application = new Hakemus(json);
application.isHakutoiveidenMuokkaus = false;
application.migriJwt = data.migriJwt
application.migriUrl = data.migriUrl
return application;
});
if($scope.applications.length > 0) {
Expand Down
4 changes: 3 additions & 1 deletion src/main/js/directives/migri.html
Expand Up @@ -3,5 +3,7 @@
<strong>{{ localization('migri.otsikko') }}</strong>
</header>
<div ng-bind-html="localization('migri.ohje-teksti')"></div>
<div class="linkki" ng-bind-html="localization('migri.linkki-teksti')"></div>
<div>
<a class="linkki" href="{{parsedUrl}}" target="_blank">{{localization('migri.linkki-teksti')}}</a>
</div>
</div>
6 changes: 5 additions & 1 deletion src/main/js/directives/migri.js
Expand Up @@ -4,11 +4,15 @@ export default function () {
return {
restrict: 'E',
scope: {
migri: '&'
migri: '&migri',
token: '@token',
url: '@url'
},
template: require('./migri.html'),
link: function (scope, element, attrs) {
scope.localization = localize;
scope.tokenParam = scope.token ? "?token=" + scope.token : ""
scope.parsedUrl = scope.url + scope.tokenParam;
}
}
}
2 changes: 2 additions & 0 deletions src/main/js/interceptors/nonSensitiveHakemus.js
Expand Up @@ -28,6 +28,8 @@ export default ['$cookies', function HakemusInterceptor($cookies) {
if (shouldAuthenticate(response.config) && response.data && response.data.jsonWebToken) {
setBearerToken($cookies, response.data.jsonWebToken);
response.oiliJwt = response.data.oiliJwt;
response.migriJwt = response.data.migriJwt;
response.migriUrl = response.data.migriUrl;
response.data = response.data.response
}
return response
Expand Down
2 changes: 2 additions & 0 deletions src/main/js/models/hakemus.js
Expand Up @@ -27,6 +27,8 @@ export default class Hakemus {
postOffice: json.hakemus.postOffice
};
this.oiliJwt = null;
this.migriJwt = null;
this.migriUrl = null;
this.hakemusSource = json.hakemusSource;
this.previewUrl = json.previewUrl;
}
Expand Down
Expand Up @@ -19,6 +19,7 @@ host.virkailija={{host_virkailija}}
host.oppija={{host_oppija}}

omatsivut.crypto.aes.key={{omatsivut_crypto_aes_key}}
omatsivut.migri.crypto.hmac.key={{omatsivut_migri_crypto_hmac_key}}
omatsivut.crypto.hmac.key={{omatsivut_crypto_hmac_key}}

cas.url=https://{{host_virkailija}}/cas
Expand Down Expand Up @@ -193,3 +194,5 @@ oppija.base.url.sv={{oppija_base_url_sv}}
omatsivut.kohdejoukot.korkeakoulu={{omatsivut_kohdejoukot_korkeakoulu | default('haunkohdejoukko_12')}}
omatsivut.kohdejoukot.toinen-aste={{omatsivut_kohdejoukot_toinenaste | default('haunkohdejoukko_11,haunkohdejoukko_17,haunkohdejoukko_20,haunkohdejoukko_23,haunkohdejoukko_24')}}
omatsivut.kohdejoukon-tarkenteet.siirtohaku={{omatsivut_kohdejoukontarkenteet_siirtohaku | default('haunkohdejoukontarkenne_1')}}

omatsivut.migri.url={{omatsivut_migri_url}}
1 change: 1 addition & 0 deletions src/main/resources/oph-configuration/dev-vars.yml
Expand Up @@ -31,6 +31,7 @@ mongodb_hakemus_password: ""
omatsivut_cas_ticket_url: "http://localhost/cas/v1/tickets"
omatsivut_crypto_aes_key: "akuankkaakuankka"
omatsivut_crypto_hmac_key: "akuankkaakuankkaakuankkaakuankka"
omatsivut_migri_crypto_hmac_key: "roopeankkaroopeankkaroopeankkaro"
omatsivut_haku_app_username: ""
omatsivut_haku_app_password: ""
omatsivut_authentication_service_username: ""
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/translations/en.json
Expand Up @@ -218,8 +218,9 @@

"migri": {
"otsikko": "You can now apply for a residence permit",
"ohje-teksti": "<ul><li>Please first see instructions on how to apply for a residence permit: <a href='https://migri.fi/en/guide-for-students' target='_blank'>Guide for students</a></li><li>In order to apply for the residence permit, you need to attach your national learner ID on the residence permit application. <a href='/konfo/en/sivu/national-learner-id' target='_blank'>Learn more about the national learner ID</a></li></ul>",
"linkki-teksti": "<a href='https://migri.fi/en/residence-permit-application-for-studies' target='_blank'>Click here to apply for the residence permit</a>"
"ohje-teksti": "<ul><li>Please first see instructions on how to apply for a residence permit: <a href='https://migri.fi/en/guide-for-students' target='_blank'>Guide for students</a></li><li>In order to apply for the residence permit, you need to attach your national learner ID on the residence permit application. <a href='/konfo/en/sivu/national-learner-id' target='_blank'>Learn more about the national learner ID</a></li><li>Your national learner ID is automatically provided on your residence permit application via this link.</li></ul>",
"linkki-teksti": "Click here to apply for the residence permit",
"linkki-pohja": "https://enterfinland.fi/eServices/chooseapplicationtype"
},

"emailNote": {
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/translations/fi.json
Expand Up @@ -218,8 +218,9 @@

"migri": {
"otsikko": "Voit nyt hakea oleskelulupaa",
"ohje-teksti": "<ul><li>Tutustuthan ensin oleskeluluvan hakuohjeisiin: <a href='https://migri.fi/opiskelijan-opas' target='_blank'>Opiskelijan opas</a></li><li>Sinun pitää lisätä oleskelulupahakemuksellesi oppijanumerosi. <a href='/konfo/fi/sivu/oppijanumero' target='_blank'>Lue lisää oppijanumerosta</a></li></ul>",
"linkki-teksti": "<a href='https://migri.fi/opiskelijan-oleskelulupahakemus' target='_blank'>Siirry tästä oleskeluluvan hakemiseen</a>"
"ohje-teksti": "<ul><li>Tutustuthan ensin oleskeluluvan hakuohjeisiin: <a href='https://migri.fi/opiskelijan-opas' target='_blank'>Opiskelijan opas</a></li><li>Sinun pitää lisätä oleskelulupahakemuksellesi oppijanumerosi. <a href='/konfo/fi/sivu/oppijanumero' target='_blank'>Lue lisää oppijanumerosta</a></li><li>Oppijanumerosi välittyy tämän linkin kautta automaattisesti oleskelulupahakemukselle.</li></ul>",
"linkki-teksti": "Siirry tästä oleskeluluvan hakemiseen",
"linkki-pohja": "https://enterfinland.fi/eServices/chooseapplicationtype"
},

"emailNote": {
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/translations/sv.json
Expand Up @@ -218,8 +218,9 @@

"migri": {
"otsikko": "Du kan nu ansöka om uppehållstillstånd",
"ohje-teksti": "<ul><li>Bekanta dig först med anvisningarna för att ansöka om uppehållstillstånd: <a href='https://migri.fi/sv/guiden-for-studerande' target='_blank'>Guiden för studerande</a></li><li>Du måste lägga in ditt studentnummer på din ansökan om uppehållstillstånd.<a href='/konfo/sv/sivu/studentnummer' target='_blank'>Läs mera om studentnummer</a></li></ul>",
"linkki-teksti": "<a href='https://migri.fi/sv/ansokan-om-uppehallstillstand-for-studier' target='_blank'>Klicka här för att ansöka om uppehållstillstånd</a>"
"ohje-teksti": "<ul><li>Bekanta dig först med anvisningarna för att ansöka om uppehållstillstånd: <a href='https://migri.fi/sv/guiden-for-studerande' target='_blank'>Guiden för studerande</a></li><li>Du måste lägga in ditt studentnummer på din ansökan om uppehållstillstånd. <a href='/konfo/sv/sivu/studentnummer' target='_blank'>Läs mera om studentnummer</a></li><li>Via den här länken förmedlas ditt studerandenummer automatiskt till din ansökan om uppehållstillstånd.</li></ul>",
"linkki-teksti": "Klicka här för att ansöka om uppehållstillstånd",
"linkki-pohja": "https://enterfinland.fi/eServices/chooseapplicationtype"
},

"emailNote": {
Expand Down
Expand Up @@ -28,11 +28,14 @@ case class ApplicationSettings(config: Config) extends GroupEmailerSettings(conf
leakDetectionThresholdMillis = getLong(config, "omatsivut.db.leakDetectionThresholdMillis")
)

val migriUrl = config.getString("omatsivut.migri.url")

val sessionTimeoutSeconds = getInt(config, "omatsivut.sessionTimeoutSeconds")
val sessionCleanupCronString = getString(config, "omatsivut.sessionCleanupCronString")

val aesKey : String = config.getString("omatsivut.crypto.aes.key")
val hmacKey : String = config.getString("omatsivut.crypto.hmac.key")
val hmacKeyMigri : String = config.getString("omatsivut.migri.crypto.hmac.key")

val oppijaBaseUrlEn = config.getString("oppija.base.url.en")
val oppijaBaseUrlFi = config.getString("oppija.base.url.fi")
Expand Down
15 changes: 15 additions & 0 deletions src/main/scala/fi/vm/sade/omatsivut/security/JsonWebToken.scala
Expand Up @@ -11,6 +11,21 @@ import scala.util.{Failure, Success, Try}
case class HakemusJWT(oid: Oid, answersFromThisSession: Set[AnswerId], personOid: Oid)
case class OiliJWT(hakijaOid: Oid, expires: Long)

case class MigriJWT(hakijaOid: Oid, expires: Long)

class MigriJsonWebToken(val secret: String) {
implicit val jsonFormats = formats(NoTypeHints)

if (secret.getBytes.size * 8 < 256) throw new RuntimeException("(MIGRI) HMAC secret has to be at least 256 bits")

val algo = JwtAlgorithm.HS256

def createMigriJWT(hakijaOid: String): String = {
val migriJwt = MigriJWT(hakijaOid, System.currentTimeMillis + (3600 * 2 * 1000)) //two hours expiry time
JwtJson4s.encode(write(migriJwt), secret, algo)
}
}

class JsonWebToken(val secret: String) {
implicit val jsonFormats = formats(NoTypeHints)

Expand Down
Expand Up @@ -14,7 +14,7 @@ import fi.vm.sade.hakemuseditori.viestintapalvelu.{AccessibleHtml, Pdf}
import fi.vm.sade.omatsivut.config.AppConfig
import fi.vm.sade.omatsivut.config.AppConfig.AppConfig
import fi.vm.sade.omatsivut.hakemuspreview.HakemusPreviewGeneratorComponent
import fi.vm.sade.omatsivut.security.{AuthenticationRequiringServlet, SessionService}
import fi.vm.sade.omatsivut.security.{AuthenticationRequiringServlet, JsonWebToken, MigriJsonWebToken, SessionService}
import fi.vm.sade.omatsivut.vastaanotto.{Vastaanotto, VastaanottoComponent}
import fi.vm.sade.utils.cas.{CasAuthenticatingClient, CasClient, CasParams}
import org.http4s.client.blaze
Expand All @@ -41,6 +41,8 @@ trait ApplicationsServletContainer {
extends OmatSivutServletBase
with JsonFormats with JacksonJsonSupport with AuthenticationRequiringServlet with HakemusEditoriUserContext {

private val migriJwt = new MigriJsonWebToken(appConfig.settings.hmacKeyMigri)

def user = Oppija(personOid())
private val hakemusEditori = newEditor(this)
protected val applicationDescription = "Oppijan henkilökohtaisen palvelun REST API, jolla voi hakea ja muokata hakemuksia ja omia tietoja"
Expand Down Expand Up @@ -71,10 +73,20 @@ trait ApplicationsServletContainer {
val oid = personOid()
hakemusEditori.fetchByPersonOid(request, oid, Fetch) match {
case FullSuccess(hakemukset) =>
Map("allApplicationsFetched" -> true, "applications" -> hakemukset)
Map(
"allApplicationsFetched" -> true,
"applications" -> hakemukset,
"migriJwt" -> migriJwt.createMigriJWT(oid),
"migriUrl" -> appConfig.settings.migriUrl
)
case PartialSuccess(hakemukset, exceptions) =>
exceptions.foreach(logger.warn(s"Failed to fetch all applications for oid $oid",_))
Map("allApplicationsFetched" -> false, "applications" -> hakemukset)
Map(
"allApplicationsFetched" -> false,
"applications" -> hakemukset,
"migriJwt" -> migriJwt.createMigriJWT(oid),
"migriUrl" -> appConfig.settings.migriUrl
)
case FullFailure(exceptions) =>
exceptions.foreach(logger.error(s"Failed to fetch applications for oid $oid", _))
throw exceptions.head
Expand Down
Expand Up @@ -14,7 +14,7 @@ import fi.vm.sade.hakemuseditori.viestintapalvelu.{AccessibleHtml, Pdf}
import fi.vm.sade.omatsivut.NonSensitiveHakemusInfo.answerIds
import fi.vm.sade.omatsivut.config.AppConfig.AppConfig
import fi.vm.sade.omatsivut.oppijantunnistus.{ExpiredTokenException, InvalidTokenException, OppijanTunnistusComponent}
import fi.vm.sade.omatsivut.security.{HakemusJWT, JsonWebToken}
import fi.vm.sade.omatsivut.security.{HakemusJWT, JsonWebToken, MigriJsonWebToken}
import fi.vm.sade.omatsivut.vastaanotto.{Vastaanotto, VastaanottoComponent}
import fi.vm.sade.omatsivut.{NonSensitiveHakemus, NonSensitiveHakemusInfo, NonSensitiveHakemusInfoSerializer, NonSensitiveHakemusSerializer}
import org.json4s._
Expand All @@ -28,8 +28,17 @@ sealed trait InsecureResponse {
def jsonWebToken: String
}

case class InsecureHakemus(jsonWebToken: String, response: NonSensitiveHakemus) extends InsecureResponse
case class InsecureHakemusInfo(jsonWebToken: String, response: NonSensitiveHakemusInfo, oiliJwt: String = null) extends InsecureResponse
case class InsecureHakemus(
jsonWebToken: String,
response: NonSensitiveHakemus
) extends InsecureResponse
case class InsecureHakemusInfo(
jsonWebToken: String,
response: NonSensitiveHakemusInfo,
oiliJwt: String = null,
migriJwt: String = null,
migriUrl: String = null
) extends InsecureResponse

trait NonSensitiveApplicationServletContainer {
this: HakemusRepositoryComponent with
Expand All @@ -44,6 +53,8 @@ trait NonSensitiveApplicationServletContainer {
protected val applicationDescription = "Oppijan henkilökohtaisen palvelun REST API, jolla voi muokata hakemusta heikosti tunnistautuneena"
private val hakemusEditori = newEditor(this)
private val jwt = new JsonWebToken(appConfig.settings.hmacKey)
private val migriJwt = new MigriJsonWebToken(appConfig.settings.hmacKeyMigri)
private val migriUrl = appConfig.settings.migriUrl

class UnauthorizedException(msg: String) extends RuntimeException(msg)
class ForbiddenException(msg: String) extends RuntimeException(msg)
Expand Down Expand Up @@ -152,10 +163,13 @@ trait NonSensitiveApplicationServletContainer {
token <- jwtAuthorize
hakemus <- fetchHakemus(token.oid, Some(token.personOid))
} yield {
val personOid = oppijanumerorekisteriService.henkilo(token.personOid).oid
Ok(InsecureHakemusInfo(
jwt.encode(token),
new NonSensitiveHakemusInfo(hakemus, token.answersFromThisSession),
oiliJwt = jwt.createOiliJwt(oppijanumerorekisteriService.henkilo(token.personOid).oid)
oiliJwt = jwt.createOiliJwt(personOid),
migriJwt = migriJwt.createMigriJWT(personOid),
migriUrl = migriUrl
))
}).get
}
Expand Down Expand Up @@ -184,13 +198,15 @@ trait NonSensitiveApplicationServletContainer {
get("/applications/application/token/:token") {
(for {
metadata <- oppijanTunnistusService.validateToken(params("token"))
hakemus <- fetchHakemus(metadata.hakemusOid, metadata.personOid)
hakemus: HakemusInfo <- fetchHakemus(metadata.hakemusOid, metadata.personOid)
} yield {
val personOid = oppijanumerorekisteriService.henkilo(hakemus.hakemus.personOid).oid
Ok(InsecureHakemusInfo(
jwt.encode(HakemusJWT(metadata.hakemusOid, Set(), hakemus.hakemus.personOid)),
new NonSensitiveHakemusInfo(hakemus, Set()),
oiliJwt = jwt.createOiliJwt(
oppijanumerorekisteriService.henkilo(hakemus.hakemus.personOid).oid)
oiliJwt = jwt.createOiliJwt(personOid),
migriJwt = migriJwt.createMigriJWT(personOid),
migriUrl = migriUrl
))
}).get
}
Expand Down

0 comments on commit e904c00

Please sign in to comment.